diff options
Diffstat (limited to 'drivers/media/dvb/b2c2')
| -rw-r--r-- | drivers/media/dvb/b2c2/Kconfig | 45 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/Makefile | 16 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-common.h | 185 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-dma.c | 172 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-eeprom.c | 147 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 678 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-hw-filter.c | 232 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-i2c.c | 288 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-misc.c | 86 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-pci.c | 450 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-reg.h | 166 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-sram.c | 363 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-usb.c | 608 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop-usb.h | 111 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop.c | 311 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop.h | 29 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop_ibi_value_be.h | 455 | ||||
| -rw-r--r-- | drivers/media/dvb/b2c2/flexcop_ibi_value_le.h | 455 |
18 files changed, 4797 insertions, 0 deletions
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig new file mode 100644 index 00000000000..9e578140074 --- /dev/null +++ b/drivers/media/dvb/b2c2/Kconfig | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | config DVB_B2C2_FLEXCOP | ||
| 2 | tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" | ||
| 3 | depends on DVB_CORE && I2C | ||
| 4 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 5 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 6 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
| 7 | select DVB_MT312 if !DVB_FE_CUSTOMISE | ||
| 8 | select DVB_NXT200X if !DVB_FE_CUSTOMISE | ||
| 9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE | ||
| 10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE | ||
| 11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | ||
| 12 | select DVB_S5H1420 if !DVB_FE_CUSTOMISE | ||
| 13 | select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE | ||
| 14 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | ||
| 15 | select DVB_CX24123 if !DVB_FE_CUSTOMISE | ||
| 16 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE | ||
| 17 | select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE | ||
| 18 | help | ||
| 19 | Support for the digital TV receiver chip made by B2C2 Inc. included in | ||
| 20 | Technisats PCI cards and USB boxes. | ||
| 21 | |||
| 22 | Say Y if you own such a device and want to use it. | ||
| 23 | |||
| 24 | config DVB_B2C2_FLEXCOP_PCI | ||
| 25 | tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI" | ||
| 26 | depends on DVB_B2C2_FLEXCOP && PCI && I2C | ||
| 27 | help | ||
| 28 | Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2. | ||
| 29 | |||
| 30 | Say Y if you own such a device and want to use it. | ||
| 31 | |||
| 32 | config DVB_B2C2_FLEXCOP_USB | ||
| 33 | tristate "Technisat/B2C2 Air/Sky/Cable2PC USB" | ||
| 34 | depends on DVB_B2C2_FLEXCOP && USB && I2C | ||
| 35 | help | ||
| 36 | Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2, | ||
| 37 | |||
| 38 | Say Y if you own such a device and want to use it. | ||
| 39 | |||
| 40 | config DVB_B2C2_FLEXCOP_DEBUG | ||
| 41 | bool "Enable debug for the B2C2 FlexCop drivers" | ||
| 42 | depends on DVB_B2C2_FLEXCOP | ||
| 43 | help | ||
| 44 | Say Y if you want to enable the module option to control debug messages | ||
| 45 | of all B2C2 FlexCop drivers. | ||
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile new file mode 100644 index 00000000000..b97cf7208a1 --- /dev/null +++ b/drivers/media/dvb/b2c2/Makefile | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ | ||
| 2 | flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o | ||
| 3 | obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o | ||
| 4 | |||
| 5 | ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) | ||
| 6 | b2c2-flexcop-objs += flexcop-dma.o | ||
| 7 | endif | ||
| 8 | |||
| 9 | b2c2-flexcop-pci-objs = flexcop-pci.o | ||
| 10 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o | ||
| 11 | |||
| 12 | b2c2-flexcop-usb-objs = flexcop-usb.o | ||
| 13 | obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o | ||
| 14 | |||
| 15 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | ||
| 16 | EXTRA_CFLAGS += -Idrivers/media/common/tuners/ | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h new file mode 100644 index 00000000000..437912e4982 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-common.h | |||
| @@ -0,0 +1,185 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-common.h - common header file for device-specific source files | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #ifndef __FLEXCOP_COMMON_H__ | ||
| 7 | #define __FLEXCOP_COMMON_H__ | ||
| 8 | |||
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/pci.h> | ||
| 11 | #include <linux/mutex.h> | ||
| 12 | |||
| 13 | #include "flexcop-reg.h" | ||
| 14 | |||
| 15 | #include "dmxdev.h" | ||
| 16 | #include "dvb_demux.h" | ||
| 17 | #include "dvb_filter.h" | ||
| 18 | #include "dvb_net.h" | ||
| 19 | #include "dvb_frontend.h" | ||
| 20 | |||
| 21 | #define FC_MAX_FEED 256 | ||
| 22 | |||
| 23 | #ifndef FC_LOG_PREFIX | ||
| 24 | #warning please define a log prefix for your file, using a default one | ||
| 25 | #define FC_LOG_PREFIX "b2c2-undef" | ||
| 26 | #endif | ||
| 27 | |||
| 28 | /* Steal from usb.h */ | ||
| 29 | #undef err | ||
| 30 | #define err(format, arg...) \ | ||
| 31 | printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg) | ||
| 32 | #undef info | ||
| 33 | #define info(format, arg...) \ | ||
| 34 | printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg) | ||
| 35 | #undef warn | ||
| 36 | #define warn(format, arg...) \ | ||
| 37 | printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg) | ||
| 38 | |||
| 39 | struct flexcop_dma { | ||
| 40 | struct pci_dev *pdev; | ||
| 41 | |||
| 42 | u8 *cpu_addr0; | ||
| 43 | dma_addr_t dma_addr0; | ||
| 44 | u8 *cpu_addr1; | ||
| 45 | dma_addr_t dma_addr1; | ||
| 46 | u32 size; /* size of each address in bytes */ | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct flexcop_i2c_adapter { | ||
| 50 | struct flexcop_device *fc; | ||
| 51 | struct i2c_adapter i2c_adap; | ||
| 52 | |||
| 53 | u8 no_base_addr; | ||
| 54 | flexcop_i2c_port_t port; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /* Control structure for data definitions that are common to | ||
| 58 | * the B2C2-based PCI and USB devices. | ||
| 59 | */ | ||
| 60 | struct flexcop_device { | ||
| 61 | /* general */ | ||
| 62 | struct device *dev; /* for firmware_class */ | ||
| 63 | |||
| 64 | #define FC_STATE_DVB_INIT 0x01 | ||
| 65 | #define FC_STATE_I2C_INIT 0x02 | ||
| 66 | #define FC_STATE_FE_INIT 0x04 | ||
| 67 | int init_state; | ||
| 68 | |||
| 69 | /* device information */ | ||
| 70 | int has_32_hw_pid_filter; | ||
| 71 | flexcop_revision_t rev; | ||
| 72 | flexcop_device_type_t dev_type; | ||
| 73 | flexcop_bus_t bus_type; | ||
| 74 | |||
| 75 | /* dvb stuff */ | ||
| 76 | struct dvb_adapter dvb_adapter; | ||
| 77 | struct dvb_frontend *fe; | ||
| 78 | struct dvb_net dvbnet; | ||
| 79 | struct dvb_demux demux; | ||
| 80 | struct dmxdev dmxdev; | ||
| 81 | struct dmx_frontend hw_frontend; | ||
| 82 | struct dmx_frontend mem_frontend; | ||
| 83 | int (*fe_sleep) (struct dvb_frontend *); | ||
| 84 | |||
| 85 | struct flexcop_i2c_adapter fc_i2c_adap[3]; | ||
| 86 | struct mutex i2c_mutex; | ||
| 87 | struct module *owner; | ||
| 88 | |||
| 89 | /* options and status */ | ||
| 90 | int extra_feedcount; | ||
| 91 | int feedcount; | ||
| 92 | int pid_filtering; | ||
| 93 | int fullts_streaming_state; | ||
| 94 | |||
| 95 | /* bus specific callbacks */ | ||
| 96 | flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, | ||
| 97 | flexcop_ibi_register); | ||
| 98 | int (*write_ibi_reg) (struct flexcop_device *, | ||
| 99 | flexcop_ibi_register, flexcop_ibi_value); | ||
| 100 | int (*i2c_request) (struct flexcop_i2c_adapter *, | ||
| 101 | flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); | ||
| 102 | int (*stream_control) (struct flexcop_device *, int); | ||
| 103 | int (*get_mac_addr) (struct flexcop_device *fc, int extended); | ||
| 104 | void *bus_specific; | ||
| 105 | }; | ||
| 106 | |||
| 107 | /* exported prototypes */ | ||
| 108 | |||
| 109 | /* from flexcop.c */ | ||
| 110 | void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len); | ||
| 111 | void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no); | ||
| 112 | |||
| 113 | struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len); | ||
| 114 | void flexcop_device_kfree(struct flexcop_device *); | ||
| 115 | |||
| 116 | int flexcop_device_initialize(struct flexcop_device *); | ||
| 117 | void flexcop_device_exit(struct flexcop_device *fc); | ||
| 118 | void flexcop_reset_block_300(struct flexcop_device *fc); | ||
| 119 | |||
| 120 | /* from flexcop-dma.c */ | ||
| 121 | int flexcop_dma_allocate(struct pci_dev *pdev, | ||
| 122 | struct flexcop_dma *dma, u32 size); | ||
| 123 | void flexcop_dma_free(struct flexcop_dma *dma); | ||
| 124 | |||
| 125 | int flexcop_dma_control_timer_irq(struct flexcop_device *fc, | ||
| 126 | flexcop_dma_index_t no, int onoff); | ||
| 127 | int flexcop_dma_control_size_irq(struct flexcop_device *fc, | ||
| 128 | flexcop_dma_index_t no, int onoff); | ||
| 129 | int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, | ||
| 130 | flexcop_dma_index_t dma_idx); | ||
| 131 | int flexcop_dma_xfer_control(struct flexcop_device *fc, | ||
| 132 | flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, | ||
| 133 | int onoff); | ||
| 134 | int flexcop_dma_config_timer(struct flexcop_device *fc, | ||
| 135 | flexcop_dma_index_t dma_idx, u8 cycles); | ||
| 136 | |||
| 137 | /* from flexcop-eeprom.c */ | ||
| 138 | /* the PCI part uses this call to get the MAC address, the USB part has its own */ | ||
| 139 | int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended); | ||
| 140 | |||
| 141 | /* from flexcop-i2c.c */ | ||
| 142 | /* the PCI part uses this a i2c_request callback, whereas the usb part has its own | ||
| 143 | * one. We have it in flexcop-i2c.c, because it is going via the actual | ||
| 144 | * I2C-channel of the flexcop. | ||
| 145 | */ | ||
| 146 | int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t, | ||
| 147 | u8 chipaddr, u8 addr, u8 *buf, u16 len); | ||
| 148 | |||
| 149 | /* from flexcop-sram.c */ | ||
| 150 | int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, | ||
| 151 | flexcop_sram_dest_target_t target); | ||
| 152 | void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s); | ||
| 153 | void flexcop_sram_ctrl(struct flexcop_device *fc, | ||
| 154 | int usb_wan, int sramdma, int maximumfill); | ||
| 155 | |||
| 156 | /* global prototypes for the flexcop-chip */ | ||
| 157 | /* from flexcop-fe-tuner.c */ | ||
| 158 | int flexcop_frontend_init(struct flexcop_device *fc); | ||
| 159 | void flexcop_frontend_exit(struct flexcop_device *fc); | ||
| 160 | |||
| 161 | /* from flexcop-i2c.c */ | ||
| 162 | int flexcop_i2c_init(struct flexcop_device *fc); | ||
| 163 | void flexcop_i2c_exit(struct flexcop_device *fc); | ||
| 164 | |||
| 165 | /* from flexcop-sram.c */ | ||
| 166 | int flexcop_sram_init(struct flexcop_device *fc); | ||
| 167 | |||
| 168 | /* from flexcop-misc.c */ | ||
| 169 | void flexcop_determine_revision(struct flexcop_device *fc); | ||
| 170 | void flexcop_device_name(struct flexcop_device *fc, | ||
| 171 | const char *prefix, const char *suffix); | ||
| 172 | void flexcop_dump_reg(struct flexcop_device *fc, | ||
| 173 | flexcop_ibi_register reg, int num); | ||
| 174 | |||
| 175 | /* from flexcop-hw-filter.c */ | ||
| 176 | int flexcop_pid_feed_control(struct flexcop_device *fc, | ||
| 177 | struct dvb_demux_feed *dvbdmxfeed, int onoff); | ||
| 178 | void flexcop_hw_filter_init(struct flexcop_device *fc); | ||
| 179 | |||
| 180 | void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); | ||
| 181 | |||
| 182 | void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); | ||
| 183 | void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff); | ||
| 184 | |||
| 185 | #endif | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c new file mode 100644 index 00000000000..2881e0d956a --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-dma.c | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-dma.c - configuring and controlling the DMA of the FlexCop | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include "flexcop.h" | ||
| 7 | |||
| 8 | int flexcop_dma_allocate(struct pci_dev *pdev, | ||
| 9 | struct flexcop_dma *dma, u32 size) | ||
| 10 | { | ||
| 11 | u8 *tcpu; | ||
| 12 | dma_addr_t tdma = 0; | ||
| 13 | |||
| 14 | if (size % 2) { | ||
| 15 | err("dma buffersize has to be even."); | ||
| 16 | return -EINVAL; | ||
| 17 | } | ||
| 18 | |||
| 19 | if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) { | ||
| 20 | dma->pdev = pdev; | ||
| 21 | dma->cpu_addr0 = tcpu; | ||
| 22 | dma->dma_addr0 = tdma; | ||
| 23 | dma->cpu_addr1 = tcpu + size/2; | ||
| 24 | dma->dma_addr1 = tdma + size/2; | ||
| 25 | dma->size = size/2; | ||
| 26 | return 0; | ||
| 27 | } | ||
| 28 | return -ENOMEM; | ||
| 29 | } | ||
| 30 | EXPORT_SYMBOL(flexcop_dma_allocate); | ||
| 31 | |||
| 32 | void flexcop_dma_free(struct flexcop_dma *dma) | ||
| 33 | { | ||
| 34 | pci_free_consistent(dma->pdev, dma->size*2, | ||
| 35 | dma->cpu_addr0, dma->dma_addr0); | ||
| 36 | memset(dma,0,sizeof(struct flexcop_dma)); | ||
| 37 | } | ||
| 38 | EXPORT_SYMBOL(flexcop_dma_free); | ||
| 39 | |||
| 40 | int flexcop_dma_config(struct flexcop_device *fc, | ||
| 41 | struct flexcop_dma *dma, | ||
| 42 | flexcop_dma_index_t dma_idx) | ||
| 43 | { | ||
| 44 | flexcop_ibi_value v0x0,v0x4,v0xc; | ||
| 45 | v0x0.raw = v0x4.raw = v0xc.raw = 0; | ||
| 46 | |||
| 47 | v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; | ||
| 48 | v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; | ||
| 49 | v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; | ||
| 50 | |||
| 51 | if ((dma_idx & FC_DMA_1) == dma_idx) { | ||
| 52 | fc->write_ibi_reg(fc,dma1_000,v0x0); | ||
| 53 | fc->write_ibi_reg(fc,dma1_004,v0x4); | ||
| 54 | fc->write_ibi_reg(fc,dma1_00c,v0xc); | ||
| 55 | } else if ((dma_idx & FC_DMA_2) == dma_idx) { | ||
| 56 | fc->write_ibi_reg(fc,dma2_010,v0x0); | ||
| 57 | fc->write_ibi_reg(fc,dma2_014,v0x4); | ||
| 58 | fc->write_ibi_reg(fc,dma2_01c,v0xc); | ||
| 59 | } else { | ||
| 60 | err("either DMA1 or DMA2 can be configured within one " | ||
| 61 | "flexcop_dma_config call."); | ||
| 62 | return -EINVAL; | ||
| 63 | } | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(flexcop_dma_config); | ||
| 68 | |||
| 69 | /* start the DMA transfers, but not the DMA IRQs */ | ||
| 70 | int flexcop_dma_xfer_control(struct flexcop_device *fc, | ||
| 71 | flexcop_dma_index_t dma_idx, | ||
| 72 | flexcop_dma_addr_index_t index, | ||
| 73 | int onoff) | ||
| 74 | { | ||
| 75 | flexcop_ibi_value v0x0,v0xc; | ||
| 76 | flexcop_ibi_register r0x0,r0xc; | ||
| 77 | |||
| 78 | if ((dma_idx & FC_DMA_1) == dma_idx) { | ||
| 79 | r0x0 = dma1_000; | ||
| 80 | r0xc = dma1_00c; | ||
| 81 | } else if ((dma_idx & FC_DMA_2) == dma_idx) { | ||
| 82 | r0x0 = dma2_010; | ||
| 83 | r0xc = dma2_01c; | ||
| 84 | } else { | ||
| 85 | err("either transfer DMA1 or DMA2 can be started within one " | ||
| 86 | "flexcop_dma_xfer_control call."); | ||
| 87 | return -EINVAL; | ||
| 88 | } | ||
| 89 | |||
| 90 | v0x0 = fc->read_ibi_reg(fc,r0x0); | ||
| 91 | v0xc = fc->read_ibi_reg(fc,r0xc); | ||
| 92 | |||
| 93 | deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw); | ||
| 94 | deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw); | ||
| 95 | |||
| 96 | if (index & FC_DMA_SUBADDR_0) | ||
| 97 | v0x0.dma_0x0.dma_0start = onoff; | ||
| 98 | |||
| 99 | if (index & FC_DMA_SUBADDR_1) | ||
| 100 | v0xc.dma_0xc.dma_1start = onoff; | ||
| 101 | |||
| 102 | fc->write_ibi_reg(fc,r0x0,v0x0); | ||
| 103 | fc->write_ibi_reg(fc,r0xc,v0xc); | ||
| 104 | |||
| 105 | deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw); | ||
| 106 | deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw); | ||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | EXPORT_SYMBOL(flexcop_dma_xfer_control); | ||
| 110 | |||
| 111 | static int flexcop_dma_remap(struct flexcop_device *fc, | ||
| 112 | flexcop_dma_index_t dma_idx, | ||
| 113 | int onoff) | ||
| 114 | { | ||
| 115 | flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; | ||
| 116 | flexcop_ibi_value v = fc->read_ibi_reg(fc,r); | ||
| 117 | deb_info("%s\n",__func__); | ||
| 118 | v.dma_0xc.remap_enable = onoff; | ||
| 119 | fc->write_ibi_reg(fc,r,v); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | int flexcop_dma_control_size_irq(struct flexcop_device *fc, | ||
| 124 | flexcop_dma_index_t no, | ||
| 125 | int onoff) | ||
| 126 | { | ||
| 127 | flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); | ||
| 128 | |||
| 129 | if (no & FC_DMA_1) | ||
| 130 | v.ctrl_208.DMA1_IRQ_Enable_sig = onoff; | ||
| 131 | |||
| 132 | if (no & FC_DMA_2) | ||
| 133 | v.ctrl_208.DMA2_IRQ_Enable_sig = onoff; | ||
| 134 | |||
| 135 | fc->write_ibi_reg(fc,ctrl_208,v); | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | EXPORT_SYMBOL(flexcop_dma_control_size_irq); | ||
| 139 | |||
| 140 | int flexcop_dma_control_timer_irq(struct flexcop_device *fc, | ||
| 141 | flexcop_dma_index_t no, | ||
| 142 | int onoff) | ||
| 143 | { | ||
| 144 | flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); | ||
| 145 | |||
| 146 | if (no & FC_DMA_1) | ||
| 147 | v.ctrl_208.DMA1_Timer_Enable_sig = onoff; | ||
| 148 | |||
| 149 | if (no & FC_DMA_2) | ||
| 150 | v.ctrl_208.DMA2_Timer_Enable_sig = onoff; | ||
| 151 | |||
| 152 | fc->write_ibi_reg(fc,ctrl_208,v); | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | EXPORT_SYMBOL(flexcop_dma_control_timer_irq); | ||
| 156 | |||
| 157 | /* 1 cycles = 1.97 msec */ | ||
| 158 | int flexcop_dma_config_timer(struct flexcop_device *fc, | ||
| 159 | flexcop_dma_index_t dma_idx, u8 cycles) | ||
| 160 | { | ||
| 161 | flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; | ||
| 162 | flexcop_ibi_value v = fc->read_ibi_reg(fc,r); | ||
| 163 | |||
| 164 | flexcop_dma_remap(fc,dma_idx,0); | ||
| 165 | |||
| 166 | deb_info("%s\n",__func__); | ||
| 167 | v.dma_0x4_write.dmatimer = cycles; | ||
| 168 | fc->write_ibi_reg(fc,r,v); | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | EXPORT_SYMBOL(flexcop_dma_config_timer); | ||
| 172 | |||
diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c new file mode 100644 index 00000000000..a25373a9bd8 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading) | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include "flexcop.h" | ||
| 7 | |||
| 8 | #if 0 | ||
| 9 | /*EEPROM (Skystar2 has one "24LC08B" chip on board) */ | ||
| 10 | static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len) | ||
| 11 | { | ||
| 12 | return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len); | ||
| 13 | } | ||
| 14 | |||
| 15 | static int eeprom_lrc_write(struct adapter *adapter, u32 addr, | ||
| 16 | u32 len, u8 *wbuf, u8 *rbuf, int retries) | ||
| 17 | { | ||
| 18 | int i; | ||
| 19 | |||
| 20 | for (i = 0; i < retries; i++) { | ||
| 21 | if (eeprom_write(adapter, addr, wbuf, len) == len) { | ||
| 22 | if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1) | ||
| 23 | return 1; | ||
| 24 | } | ||
| 25 | } | ||
| 26 | return 0; | ||
| 27 | } | ||
| 28 | |||
| 29 | /* These functions could be used to unlock SkyStar2 cards. */ | ||
| 30 | |||
| 31 | static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len) | ||
| 32 | { | ||
| 33 | u8 rbuf[20]; | ||
| 34 | u8 wbuf[20]; | ||
| 35 | |||
| 36 | if (len != 16) | ||
| 37 | return 0; | ||
| 38 | |||
| 39 | memcpy(wbuf, key, len); | ||
| 40 | wbuf[16] = 0; | ||
| 41 | wbuf[17] = 0; | ||
| 42 | wbuf[18] = 0; | ||
| 43 | wbuf[19] = calc_lrc(wbuf, 19); | ||
| 44 | return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4); | ||
| 45 | } | ||
| 46 | |||
| 47 | static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len) | ||
| 48 | { | ||
| 49 | u8 buf[20]; | ||
| 50 | |||
| 51 | if (len != 16) | ||
| 52 | return 0; | ||
| 53 | |||
| 54 | if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0) | ||
| 55 | return 0; | ||
| 56 | |||
| 57 | memcpy(key, buf, len); | ||
| 58 | return 1; | ||
| 59 | } | ||
| 60 | |||
| 61 | static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac) | ||
| 62 | { | ||
| 63 | u8 tmp[8]; | ||
| 64 | |||
| 65 | if (type != 0) { | ||
| 66 | tmp[0] = mac[0]; | ||
| 67 | tmp[1] = mac[1]; | ||
| 68 | tmp[2] = mac[2]; | ||
| 69 | tmp[3] = mac[5]; | ||
| 70 | tmp[4] = mac[6]; | ||
| 71 | tmp[5] = mac[7]; | ||
| 72 | } else { | ||
| 73 | tmp[0] = mac[0]; | ||
| 74 | tmp[1] = mac[1]; | ||
| 75 | tmp[2] = mac[2]; | ||
| 76 | tmp[3] = mac[3]; | ||
| 77 | tmp[4] = mac[4]; | ||
| 78 | tmp[5] = mac[5]; | ||
| 79 | } | ||
| 80 | |||
| 81 | tmp[6] = 0; | ||
| 82 | tmp[7] = calc_lrc(tmp, 7); | ||
| 83 | |||
| 84 | if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8) | ||
| 85 | return 1; | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int flexcop_eeprom_read(struct flexcop_device *fc, | ||
| 90 | u16 addr, u8 *buf, u16 len) | ||
| 91 | { | ||
| 92 | return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len); | ||
| 93 | } | ||
| 94 | |||
| 95 | #endif | ||
| 96 | |||
| 97 | static u8 calc_lrc(u8 *buf, int len) | ||
| 98 | { | ||
| 99 | int i; | ||
| 100 | u8 sum = 0; | ||
| 101 | for (i = 0; i < len; i++) | ||
| 102 | sum = sum ^ buf[i]; | ||
| 103 | return sum; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int flexcop_eeprom_request(struct flexcop_device *fc, | ||
| 107 | flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) | ||
| 108 | { | ||
| 109 | int i,ret = 0; | ||
| 110 | u8 chipaddr = 0x50 | ((addr >> 8) & 3); | ||
| 111 | for (i = 0; i < retries; i++) { | ||
| 112 | ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr, | ||
| 113 | addr & 0xff, buf, len); | ||
| 114 | if (ret == 0) | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, | ||
| 121 | u8 *buf, u16 len, int retries) | ||
| 122 | { | ||
| 123 | int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries); | ||
| 124 | if (ret == 0) | ||
| 125 | if (calc_lrc(buf, len - 1) != buf[len - 1]) | ||
| 126 | ret = -EINVAL; | ||
| 127 | return ret; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* JJ's comment about extended == 1: it is not presently used anywhere but was | ||
| 131 | * added to the low-level functions for possible support of EUI64 */ | ||
| 132 | int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) | ||
| 133 | { | ||
| 134 | u8 buf[8]; | ||
| 135 | int ret = 0; | ||
| 136 | |||
| 137 | if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) { | ||
| 138 | if (extended != 0) { | ||
| 139 | err("TODO: extended (EUI64) MAC addresses aren't " | ||
| 140 | "completely supported yet"); | ||
| 141 | ret = -EINVAL; | ||
| 142 | } else | ||
| 143 | memcpy(fc->dvb_adapter.proposed_mac,buf,6); | ||
| 144 | } | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr); | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c new file mode 100644 index 00000000000..850a6c60675 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
| @@ -0,0 +1,678 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include <media/tuner.h> | ||
| 7 | #include "flexcop.h" | ||
| 8 | #include "mt312.h" | ||
| 9 | #include "stv0299.h" | ||
| 10 | #include "s5h1420.h" | ||
| 11 | #include "itd1000.h" | ||
| 12 | #include "cx24113.h" | ||
| 13 | #include "cx24123.h" | ||
| 14 | #include "isl6421.h" | ||
| 15 | #include "mt352.h" | ||
| 16 | #include "bcm3510.h" | ||
| 17 | #include "nxt200x.h" | ||
| 18 | #include "dvb-pll.h" | ||
| 19 | #include "lgdt330x.h" | ||
| 20 | #include "tuner-simple.h" | ||
| 21 | #include "stv0297.h" | ||
| 22 | |||
| 23 | |||
| 24 | /* Can we use the specified front-end? Remember that if we are compiled | ||
| 25 | * into the kernel we can't call code that's in modules. */ | ||
| 26 | #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ | ||
| 27 | (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) | ||
| 28 | |||
| 29 | /* lnb control */ | ||
| 30 | #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) | ||
| 31 | static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 32 | { | ||
| 33 | struct flexcop_device *fc = fe->dvb->priv; | ||
| 34 | flexcop_ibi_value v; | ||
| 35 | deb_tuner("polarity/voltage = %u\n", voltage); | ||
| 36 | |||
| 37 | v = fc->read_ibi_reg(fc, misc_204); | ||
| 38 | switch (voltage) { | ||
| 39 | case SEC_VOLTAGE_OFF: | ||
| 40 | v.misc_204.ACPI1_sig = 1; | ||
| 41 | break; | ||
| 42 | case SEC_VOLTAGE_13: | ||
| 43 | v.misc_204.ACPI1_sig = 0; | ||
| 44 | v.misc_204.LNB_L_H_sig = 0; | ||
| 45 | break; | ||
| 46 | case SEC_VOLTAGE_18: | ||
| 47 | v.misc_204.ACPI1_sig = 0; | ||
| 48 | v.misc_204.LNB_L_H_sig = 1; | ||
| 49 | break; | ||
| 50 | default: | ||
| 51 | err("unknown SEC_VOLTAGE value"); | ||
| 52 | return -EINVAL; | ||
| 53 | } | ||
| 54 | return fc->write_ibi_reg(fc, misc_204, v); | ||
| 55 | } | ||
| 56 | #endif | ||
| 57 | |||
| 58 | #if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312) | ||
| 59 | static int flexcop_sleep(struct dvb_frontend* fe) | ||
| 60 | { | ||
| 61 | struct flexcop_device *fc = fe->dvb->priv; | ||
| 62 | if (fc->fe_sleep) | ||
| 63 | return fc->fe_sleep(fe); | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | #endif | ||
| 67 | |||
| 68 | /* SkyStar2 DVB-S rev 2.3 */ | ||
| 69 | #if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL) | ||
| 70 | static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
| 71 | { | ||
| 72 | /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ | ||
| 73 | struct flexcop_device *fc = fe->dvb->priv; | ||
| 74 | flexcop_ibi_value v; | ||
| 75 | u16 ax; | ||
| 76 | v.raw = 0; | ||
| 77 | deb_tuner("tone = %u\n",tone); | ||
| 78 | |||
| 79 | switch (tone) { | ||
| 80 | case SEC_TONE_ON: | ||
| 81 | ax = 0x01ff; | ||
| 82 | break; | ||
| 83 | case SEC_TONE_OFF: | ||
| 84 | ax = 0; | ||
| 85 | break; | ||
| 86 | default: | ||
| 87 | err("unknown SEC_TONE value"); | ||
| 88 | return -EINVAL; | ||
| 89 | } | ||
| 90 | |||
| 91 | v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */ | ||
| 92 | v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax; | ||
| 93 | v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax; | ||
| 94 | return fc->write_ibi_reg(fc,lnb_switch_freq_200,v); | ||
| 95 | } | ||
| 96 | |||
| 97 | static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data) | ||
| 98 | { | ||
| 99 | flexcop_set_tone(fe, SEC_TONE_ON); | ||
| 100 | udelay(data ? 500 : 1000); | ||
| 101 | flexcop_set_tone(fe, SEC_TONE_OFF); | ||
| 102 | udelay(data ? 1000 : 500); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data) | ||
| 106 | { | ||
| 107 | int i, par = 1, d; | ||
| 108 | for (i = 7; i >= 0; i--) { | ||
| 109 | d = (data >> i) & 1; | ||
| 110 | par ^= d; | ||
| 111 | flexcop_diseqc_send_bit(fe, d); | ||
| 112 | } | ||
| 113 | flexcop_diseqc_send_bit(fe, par); | ||
| 114 | } | ||
| 115 | |||
| 116 | static int flexcop_send_diseqc_msg(struct dvb_frontend *fe, | ||
| 117 | int len, u8 *msg, unsigned long burst) | ||
| 118 | { | ||
| 119 | int i; | ||
| 120 | |||
| 121 | flexcop_set_tone(fe, SEC_TONE_OFF); | ||
| 122 | mdelay(16); | ||
| 123 | |||
| 124 | for (i = 0; i < len; i++) | ||
| 125 | flexcop_diseqc_send_byte(fe,msg[i]); | ||
| 126 | mdelay(16); | ||
| 127 | |||
| 128 | if (burst != -1) { | ||
| 129 | if (burst) | ||
| 130 | flexcop_diseqc_send_byte(fe, 0xff); | ||
| 131 | else { | ||
| 132 | flexcop_set_tone(fe, SEC_TONE_ON); | ||
| 133 | mdelay(12); | ||
| 134 | udelay(500); | ||
| 135 | flexcop_set_tone(fe, SEC_TONE_OFF); | ||
| 136 | } | ||
| 137 | msleep(20); | ||
| 138 | } | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||
| 143 | struct dvb_diseqc_master_cmd *cmd) | ||
| 144 | { | ||
| 145 | return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0); | ||
| 146 | } | ||
| 147 | |||
| 148 | static int flexcop_diseqc_send_burst(struct dvb_frontend *fe, | ||
| 149 | fe_sec_mini_cmd_t minicmd) | ||
| 150 | { | ||
| 151 | return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd); | ||
| 152 | } | ||
| 153 | |||
| 154 | static struct mt312_config skystar23_samsung_tbdu18132_config = { | ||
| 155 | .demod_address = 0x0e, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static int skystar2_rev23_attach(struct flexcop_device *fc, | ||
| 159 | struct i2c_adapter *i2c) | ||
| 160 | { | ||
| 161 | struct dvb_frontend_ops *ops; | ||
| 162 | |||
| 163 | fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c); | ||
| 164 | if (!fc->fe) | ||
| 165 | return 0; | ||
| 166 | |||
| 167 | if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c, | ||
| 168 | DVB_PLL_SAMSUNG_TBDU18132)) | ||
| 169 | return 0; | ||
| 170 | |||
| 171 | ops = &fc->fe->ops; | ||
| 172 | ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; | ||
| 173 | ops->diseqc_send_burst = flexcop_diseqc_send_burst; | ||
| 174 | ops->set_tone = flexcop_set_tone; | ||
| 175 | ops->set_voltage = flexcop_set_voltage; | ||
| 176 | fc->fe_sleep = ops->sleep; | ||
| 177 | ops->sleep = flexcop_sleep; | ||
| 178 | return 1; | ||
| 179 | } | ||
| 180 | #else | ||
| 181 | #define skystar2_rev23_attach NULL | ||
| 182 | #endif | ||
| 183 | |||
| 184 | /* SkyStar2 DVB-S rev 2.6 */ | ||
| 185 | #if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL) | ||
| 186 | static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, | ||
| 187 | u32 srate, u32 ratio) | ||
| 188 | { | ||
| 189 | u8 aclk = 0; | ||
| 190 | u8 bclk = 0; | ||
| 191 | |||
| 192 | if (srate < 1500000) { | ||
| 193 | aclk = 0xb7; bclk = 0x47; | ||
| 194 | } else if (srate < 3000000) { | ||
| 195 | aclk = 0xb7; bclk = 0x4b; | ||
| 196 | } else if (srate < 7000000) { | ||
| 197 | aclk = 0xb7; bclk = 0x4f; | ||
| 198 | } else if (srate < 14000000) { | ||
| 199 | aclk = 0xb7; bclk = 0x53; | ||
| 200 | } else if (srate < 30000000) { | ||
| 201 | aclk = 0xb6; bclk = 0x53; | ||
| 202 | } else if (srate < 45000000) { | ||
| 203 | aclk = 0xb4; bclk = 0x51; | ||
| 204 | } | ||
| 205 | |||
| 206 | stv0299_writereg(fe, 0x13, aclk); | ||
| 207 | stv0299_writereg(fe, 0x14, bclk); | ||
| 208 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
| 209 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
| 210 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static u8 samsung_tbmu24112_inittab[] = { | ||
| 215 | 0x01, 0x15, | ||
| 216 | 0x02, 0x30, | ||
| 217 | 0x03, 0x00, | ||
| 218 | 0x04, 0x7D, | ||
| 219 | 0x05, 0x35, | ||
| 220 | 0x06, 0x02, | ||
| 221 | 0x07, 0x00, | ||
| 222 | 0x08, 0xC3, | ||
| 223 | 0x0C, 0x00, | ||
| 224 | 0x0D, 0x81, | ||
| 225 | 0x0E, 0x23, | ||
| 226 | 0x0F, 0x12, | ||
| 227 | 0x10, 0x7E, | ||
| 228 | 0x11, 0x84, | ||
| 229 | 0x12, 0xB9, | ||
| 230 | 0x13, 0x88, | ||
| 231 | 0x14, 0x89, | ||
| 232 | 0x15, 0xC9, | ||
| 233 | 0x16, 0x00, | ||
| 234 | 0x17, 0x5C, | ||
| 235 | 0x18, 0x00, | ||
| 236 | 0x19, 0x00, | ||
| 237 | 0x1A, 0x00, | ||
| 238 | 0x1C, 0x00, | ||
| 239 | 0x1D, 0x00, | ||
| 240 | 0x1E, 0x00, | ||
| 241 | 0x1F, 0x3A, | ||
| 242 | 0x20, 0x2E, | ||
| 243 | 0x21, 0x80, | ||
| 244 | 0x22, 0xFF, | ||
| 245 | 0x23, 0xC1, | ||
| 246 | 0x28, 0x00, | ||
| 247 | 0x29, 0x1E, | ||
| 248 | 0x2A, 0x14, | ||
| 249 | 0x2B, 0x0F, | ||
| 250 | 0x2C, 0x09, | ||
| 251 | 0x2D, 0x05, | ||
| 252 | 0x31, 0x1F, | ||
| 253 | 0x32, 0x19, | ||
| 254 | 0x33, 0xFE, | ||
| 255 | 0x34, 0x93, | ||
| 256 | 0xff, 0xff, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static struct stv0299_config samsung_tbmu24112_config = { | ||
| 260 | .demod_address = 0x68, | ||
| 261 | .inittab = samsung_tbmu24112_inittab, | ||
| 262 | .mclk = 88000000UL, | ||
| 263 | .invert = 0, | ||
| 264 | .skip_reinit = 0, | ||
| 265 | .lock_output = STV0299_LOCKOUTPUT_LK, | ||
| 266 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
| 267 | .min_delay_ms = 100, | ||
| 268 | .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, | ||
| 269 | }; | ||
| 270 | |||
| 271 | static int skystar2_rev26_attach(struct flexcop_device *fc, | ||
| 272 | struct i2c_adapter *i2c) | ||
| 273 | { | ||
| 274 | fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); | ||
| 275 | if (!fc->fe) | ||
| 276 | return 0; | ||
| 277 | |||
| 278 | if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c, | ||
| 279 | DVB_PLL_SAMSUNG_TBMU24112)) | ||
| 280 | return 0; | ||
| 281 | |||
| 282 | fc->fe->ops.set_voltage = flexcop_set_voltage; | ||
| 283 | fc->fe_sleep = fc->fe->ops.sleep; | ||
| 284 | fc->fe->ops.sleep = flexcop_sleep; | ||
| 285 | return 1; | ||
| 286 | |||
| 287 | } | ||
| 288 | #else | ||
| 289 | #define skystar2_rev26_attach NULL | ||
| 290 | #endif | ||
| 291 | |||
| 292 | /* SkyStar2 DVB-S rev 2.7 */ | ||
| 293 | #if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000) | ||
| 294 | static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { | ||
| 295 | .demod_address = 0x53, | ||
| 296 | .invert = 1, | ||
| 297 | .repeated_start_workaround = 1, | ||
| 298 | .serial_mpeg = 1, | ||
| 299 | }; | ||
| 300 | |||
| 301 | static struct itd1000_config skystar2_rev2_7_itd1000_config = { | ||
| 302 | .i2c_address = 0x61, | ||
| 303 | }; | ||
| 304 | |||
| 305 | static int skystar2_rev27_attach(struct flexcop_device *fc, | ||
| 306 | struct i2c_adapter *i2c) | ||
| 307 | { | ||
| 308 | flexcop_ibi_value r108; | ||
| 309 | struct i2c_adapter *i2c_tuner; | ||
| 310 | |||
| 311 | /* enable no_base_addr - no repeated start when reading */ | ||
| 312 | fc->fc_i2c_adap[0].no_base_addr = 1; | ||
| 313 | fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, | ||
| 314 | i2c); | ||
| 315 | if (!fc->fe) | ||
| 316 | goto fail; | ||
| 317 | |||
| 318 | i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); | ||
| 319 | if (!i2c_tuner) | ||
| 320 | goto fail; | ||
| 321 | |||
| 322 | fc->fe_sleep = fc->fe->ops.sleep; | ||
| 323 | fc->fe->ops.sleep = flexcop_sleep; | ||
| 324 | |||
| 325 | /* enable no_base_addr - no repeated start when reading */ | ||
| 326 | fc->fc_i2c_adap[2].no_base_addr = 1; | ||
| 327 | if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, | ||
| 328 | 0x08, 1, 1)) { | ||
| 329 | err("ISL6421 could NOT be attached"); | ||
| 330 | goto fail_isl; | ||
| 331 | } | ||
| 332 | info("ISL6421 successfully attached"); | ||
| 333 | |||
| 334 | /* the ITD1000 requires a lower i2c clock - is it a problem ? */ | ||
| 335 | r108.raw = 0x00000506; | ||
| 336 | fc->write_ibi_reg(fc, tw_sm_c_108, r108); | ||
| 337 | if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner, | ||
| 338 | &skystar2_rev2_7_itd1000_config)) { | ||
| 339 | err("ITD1000 could NOT be attached"); | ||
| 340 | /* Should i2c clock be restored? */ | ||
| 341 | goto fail_isl; | ||
| 342 | } | ||
| 343 | info("ITD1000 successfully attached"); | ||
| 344 | |||
| 345 | return 1; | ||
| 346 | |||
| 347 | fail_isl: | ||
| 348 | fc->fc_i2c_adap[2].no_base_addr = 0; | ||
| 349 | fail: | ||
| 350 | /* for the next devices we need it again */ | ||
| 351 | fc->fc_i2c_adap[0].no_base_addr = 0; | ||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | #else | ||
| 355 | #define skystar2_rev27_attach NULL | ||
| 356 | #endif | ||
| 357 | |||
| 358 | /* SkyStar2 rev 2.8 */ | ||
| 359 | #if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113) | ||
| 360 | static struct cx24123_config skystar2_rev2_8_cx24123_config = { | ||
| 361 | .demod_address = 0x55, | ||
| 362 | .dont_use_pll = 1, | ||
| 363 | .agc_callback = cx24113_agc_callback, | ||
| 364 | }; | ||
| 365 | |||
| 366 | static const struct cx24113_config skystar2_rev2_8_cx24113_config = { | ||
| 367 | .i2c_addr = 0x54, | ||
| 368 | .xtal_khz = 10111, | ||
| 369 | }; | ||
| 370 | |||
| 371 | static int skystar2_rev28_attach(struct flexcop_device *fc, | ||
| 372 | struct i2c_adapter *i2c) | ||
| 373 | { | ||
| 374 | struct i2c_adapter *i2c_tuner; | ||
| 375 | |||
| 376 | fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config, | ||
| 377 | i2c); | ||
| 378 | if (!fc->fe) | ||
| 379 | return 0; | ||
| 380 | |||
| 381 | i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe); | ||
| 382 | if (!i2c_tuner) | ||
| 383 | return 0; | ||
| 384 | |||
| 385 | if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config, | ||
| 386 | i2c_tuner)) { | ||
| 387 | err("CX24113 could NOT be attached"); | ||
| 388 | return 0; | ||
| 389 | } | ||
| 390 | info("CX24113 successfully attached"); | ||
| 391 | |||
| 392 | fc->fc_i2c_adap[2].no_base_addr = 1; | ||
| 393 | if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, | ||
| 394 | 0x08, 0, 0)) { | ||
| 395 | err("ISL6421 could NOT be attached"); | ||
| 396 | fc->fc_i2c_adap[2].no_base_addr = 0; | ||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | info("ISL6421 successfully attached"); | ||
| 400 | /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an | ||
| 401 | * IR-receiver (PIC16F818) - but the card has no input for that ??? */ | ||
| 402 | return 1; | ||
| 403 | } | ||
| 404 | #else | ||
| 405 | #define skystar2_rev28_attach NULL | ||
| 406 | #endif | ||
| 407 | |||
| 408 | /* AirStar DVB-T */ | ||
| 409 | #if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL) | ||
| 410 | static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) | ||
| 411 | { | ||
| 412 | static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; | ||
| 413 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
| 414 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; | ||
| 415 | static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 }; | ||
| 416 | static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; | ||
| 417 | |||
| 418 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
| 419 | udelay(2000); | ||
| 420 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
| 421 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
| 422 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
| 423 | mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); | ||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | |||
| 427 | static struct mt352_config samsung_tdtc9251dh0_config = { | ||
| 428 | .demod_address = 0x0f, | ||
| 429 | .demod_init = samsung_tdtc9251dh0_demod_init, | ||
| 430 | }; | ||
| 431 | |||
| 432 | static int airstar_dvbt_attach(struct flexcop_device *fc, | ||
| 433 | struct i2c_adapter *i2c) | ||
| 434 | { | ||
| 435 | fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); | ||
| 436 | if (!fc->fe) | ||
| 437 | return 0; | ||
| 438 | |||
| 439 | return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, | ||
| 440 | DVB_PLL_SAMSUNG_TDTC9251DH0); | ||
| 441 | } | ||
| 442 | #else | ||
| 443 | #define airstar_dvbt_attach NULL | ||
| 444 | #endif | ||
| 445 | |||
| 446 | /* AirStar ATSC 1st generation */ | ||
| 447 | #if FE_SUPPORTED(BCM3510) | ||
| 448 | static int flexcop_fe_request_firmware(struct dvb_frontend *fe, | ||
| 449 | const struct firmware **fw, char* name) | ||
| 450 | { | ||
| 451 | struct flexcop_device *fc = fe->dvb->priv; | ||
| 452 | return request_firmware(fw, name, fc->dev); | ||
| 453 | } | ||
| 454 | |||
| 455 | static struct bcm3510_config air2pc_atsc_first_gen_config = { | ||
| 456 | .demod_address = 0x0f, | ||
| 457 | .request_firmware = flexcop_fe_request_firmware, | ||
| 458 | }; | ||
| 459 | |||
| 460 | static int airstar_atsc1_attach(struct flexcop_device *fc, | ||
| 461 | struct i2c_adapter *i2c) | ||
| 462 | { | ||
| 463 | fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); | ||
| 464 | return fc->fe != NULL; | ||
| 465 | } | ||
| 466 | #else | ||
| 467 | #define airstar_atsc1_attach NULL | ||
| 468 | #endif | ||
| 469 | |||
| 470 | /* AirStar ATSC 2nd generation */ | ||
| 471 | #if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL) | ||
| 472 | static struct nxt200x_config samsung_tbmv_config = { | ||
| 473 | .demod_address = 0x0a, | ||
| 474 | }; | ||
| 475 | |||
| 476 | static int airstar_atsc2_attach(struct flexcop_device *fc, | ||
| 477 | struct i2c_adapter *i2c) | ||
| 478 | { | ||
| 479 | fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); | ||
| 480 | if (!fc->fe) | ||
| 481 | return 0; | ||
| 482 | |||
| 483 | return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, | ||
| 484 | DVB_PLL_SAMSUNG_TBMV); | ||
| 485 | } | ||
| 486 | #else | ||
| 487 | #define airstar_atsc2_attach NULL | ||
| 488 | #endif | ||
| 489 | |||
| 490 | /* AirStar ATSC 3rd generation */ | ||
| 491 | #if FE_SUPPORTED(LGDT330X) | ||
| 492 | static struct lgdt330x_config air2pc_atsc_hd5000_config = { | ||
| 493 | .demod_address = 0x59, | ||
| 494 | .demod_chip = LGDT3303, | ||
| 495 | .serial_mpeg = 0x04, | ||
| 496 | .clock_polarity_flip = 1, | ||
| 497 | }; | ||
| 498 | |||
| 499 | static int airstar_atsc3_attach(struct flexcop_device *fc, | ||
| 500 | struct i2c_adapter *i2c) | ||
| 501 | { | ||
| 502 | fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); | ||
| 503 | if (!fc->fe) | ||
| 504 | return 0; | ||
| 505 | |||
| 506 | return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, | ||
| 507 | TUNER_LG_TDVS_H06XF); | ||
| 508 | } | ||
| 509 | #else | ||
| 510 | #define airstar_atsc3_attach NULL | ||
| 511 | #endif | ||
| 512 | |||
| 513 | /* CableStar2 DVB-C */ | ||
| 514 | #if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL) | ||
| 515 | static u8 alps_tdee4_stv0297_inittab[] = { | ||
| 516 | 0x80, 0x01, | ||
| 517 | 0x80, 0x00, | ||
| 518 | 0x81, 0x01, | ||
| 519 | 0x81, 0x00, | ||
| 520 | 0x00, 0x48, | ||
| 521 | 0x01, 0x58, | ||
| 522 | 0x03, 0x00, | ||
| 523 | 0x04, 0x00, | ||
| 524 | 0x07, 0x00, | ||
| 525 | 0x08, 0x00, | ||
| 526 | 0x30, 0xff, | ||
| 527 | 0x31, 0x9d, | ||
| 528 | 0x32, 0xff, | ||
| 529 | 0x33, 0x00, | ||
| 530 | 0x34, 0x29, | ||
| 531 | 0x35, 0x55, | ||
| 532 | 0x36, 0x80, | ||
| 533 | 0x37, 0x6e, | ||
| 534 | 0x38, 0x9c, | ||
| 535 | 0x40, 0x1a, | ||
| 536 | 0x41, 0xfe, | ||
| 537 | 0x42, 0x33, | ||
| 538 | 0x43, 0x00, | ||
| 539 | 0x44, 0xff, | ||
| 540 | 0x45, 0x00, | ||
| 541 | 0x46, 0x00, | ||
| 542 | 0x49, 0x04, | ||
| 543 | 0x4a, 0x51, | ||
| 544 | 0x4b, 0xf8, | ||
| 545 | 0x52, 0x30, | ||
| 546 | 0x53, 0x06, | ||
| 547 | 0x59, 0x06, | ||
| 548 | 0x5a, 0x5e, | ||
| 549 | 0x5b, 0x04, | ||
| 550 | 0x61, 0x49, | ||
| 551 | 0x62, 0x0a, | ||
| 552 | 0x70, 0xff, | ||
| 553 | 0x71, 0x04, | ||
| 554 | 0x72, 0x00, | ||
| 555 | 0x73, 0x00, | ||
| 556 | 0x74, 0x0c, | ||
| 557 | 0x80, 0x20, | ||
| 558 | 0x81, 0x00, | ||
| 559 | 0x82, 0x30, | ||
| 560 | 0x83, 0x00, | ||
| 561 | 0x84, 0x04, | ||
| 562 | 0x85, 0x22, | ||
| 563 | 0x86, 0x08, | ||
| 564 | 0x87, 0x1b, | ||
| 565 | 0x88, 0x00, | ||
| 566 | 0x89, 0x00, | ||
| 567 | 0x90, 0x00, | ||
| 568 | 0x91, 0x04, | ||
| 569 | 0xa0, 0x86, | ||
| 570 | 0xa1, 0x00, | ||
| 571 | 0xa2, 0x00, | ||
| 572 | 0xb0, 0x91, | ||
| 573 | 0xb1, 0x0b, | ||
| 574 | 0xc0, 0x5b, | ||
| 575 | 0xc1, 0x10, | ||
| 576 | 0xc2, 0x12, | ||
| 577 | 0xd0, 0x02, | ||
| 578 | 0xd1, 0x00, | ||
| 579 | 0xd2, 0x00, | ||
| 580 | 0xd3, 0x00, | ||
| 581 | 0xd4, 0x02, | ||
| 582 | 0xd5, 0x00, | ||
| 583 | 0xde, 0x00, | ||
| 584 | 0xdf, 0x01, | ||
| 585 | 0xff, 0xff, | ||
| 586 | }; | ||
| 587 | |||
| 588 | static struct stv0297_config alps_tdee4_stv0297_config = { | ||
| 589 | .demod_address = 0x1c, | ||
| 590 | .inittab = alps_tdee4_stv0297_inittab, | ||
| 591 | }; | ||
| 592 | |||
| 593 | static int cablestar2_attach(struct flexcop_device *fc, | ||
| 594 | struct i2c_adapter *i2c) | ||
| 595 | { | ||
| 596 | fc->fc_i2c_adap[0].no_base_addr = 1; | ||
| 597 | fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); | ||
| 598 | if (!fc->fe) | ||
| 599 | goto fail; | ||
| 600 | |||
| 601 | /* This tuner doesn't use the stv0297's I2C gate, but instead the | ||
| 602 | * tuner is connected to a different flexcop I2C adapter. */ | ||
| 603 | if (fc->fe->ops.i2c_gate_ctrl) | ||
| 604 | fc->fe->ops.i2c_gate_ctrl(fc->fe, 0); | ||
| 605 | fc->fe->ops.i2c_gate_ctrl = NULL; | ||
| 606 | |||
| 607 | if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, | ||
| 608 | &fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4)) | ||
| 609 | goto fail; | ||
| 610 | |||
| 611 | return 1; | ||
| 612 | |||
| 613 | fail: | ||
| 614 | /* Reset for next frontend to try */ | ||
| 615 | fc->fc_i2c_adap[0].no_base_addr = 0; | ||
| 616 | return 0; | ||
| 617 | } | ||
| 618 | #else | ||
| 619 | #define cablestar2_attach NULL | ||
| 620 | #endif | ||
| 621 | |||
| 622 | static struct { | ||
| 623 | flexcop_device_type_t type; | ||
| 624 | int (*attach)(struct flexcop_device *, struct i2c_adapter *); | ||
| 625 | } flexcop_frontends[] = { | ||
| 626 | { FC_SKY_REV27, skystar2_rev27_attach }, | ||
| 627 | { FC_SKY_REV28, skystar2_rev28_attach }, | ||
| 628 | { FC_SKY_REV26, skystar2_rev26_attach }, | ||
| 629 | { FC_AIR_DVBT, airstar_dvbt_attach }, | ||
| 630 | { FC_AIR_ATSC2, airstar_atsc2_attach }, | ||
| 631 | { FC_AIR_ATSC3, airstar_atsc3_attach }, | ||
| 632 | { FC_AIR_ATSC1, airstar_atsc1_attach }, | ||
| 633 | { FC_CABLE, cablestar2_attach }, | ||
| 634 | { FC_SKY_REV23, skystar2_rev23_attach }, | ||
| 635 | }; | ||
| 636 | |||
| 637 | /* try to figure out the frontend */ | ||
| 638 | int flexcop_frontend_init(struct flexcop_device *fc) | ||
| 639 | { | ||
| 640 | int i; | ||
| 641 | for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) { | ||
| 642 | if (!flexcop_frontends[i].attach) | ||
| 643 | continue; | ||
| 644 | /* type needs to be set before, because of some workarounds | ||
| 645 | * done based on the probed card type */ | ||
| 646 | fc->dev_type = flexcop_frontends[i].type; | ||
| 647 | if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap)) | ||
| 648 | goto fe_found; | ||
| 649 | /* Clean up partially attached frontend */ | ||
| 650 | if (fc->fe) { | ||
| 651 | dvb_frontend_detach(fc->fe); | ||
| 652 | fc->fe = NULL; | ||
| 653 | } | ||
| 654 | } | ||
| 655 | fc->dev_type = FC_UNK; | ||
| 656 | err("no frontend driver found for this B2C2/FlexCop adapter"); | ||
| 657 | return -ENODEV; | ||
| 658 | |||
| 659 | fe_found: | ||
| 660 | info("found '%s' .", fc->fe->ops.info.name); | ||
| 661 | if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { | ||
| 662 | err("frontend registration failed!"); | ||
| 663 | dvb_frontend_detach(fc->fe); | ||
| 664 | fc->fe = NULL; | ||
| 665 | return -EINVAL; | ||
| 666 | } | ||
| 667 | fc->init_state |= FC_STATE_FE_INIT; | ||
| 668 | return 0; | ||
| 669 | } | ||
| 670 | |||
| 671 | void flexcop_frontend_exit(struct flexcop_device *fc) | ||
| 672 | { | ||
| 673 | if (fc->init_state & FC_STATE_FE_INIT) { | ||
| 674 | dvb_unregister_frontend(fc->fe); | ||
| 675 | dvb_frontend_detach(fc->fe); | ||
| 676 | } | ||
| 677 | fc->init_state &= ~FC_STATE_FE_INIT; | ||
| 678 | } | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c new file mode 100644 index 00000000000..77e45475f4c --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c | |||
| @@ -0,0 +1,232 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-hw-filter.c - pid and mac address filtering and control functions | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include "flexcop.h" | ||
| 7 | |||
| 8 | static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) | ||
| 9 | { | ||
| 10 | flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff); | ||
| 11 | deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); | ||
| 12 | } | ||
| 13 | |||
| 14 | void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) | ||
| 15 | { | ||
| 16 | flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); | ||
| 17 | } | ||
| 18 | |||
| 19 | static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff) | ||
| 20 | { | ||
| 21 | flexcop_set_ibi_value(ctrl_208, Null_filter_sig, onoff); | ||
| 22 | } | ||
| 23 | |||
| 24 | void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]) | ||
| 25 | { | ||
| 26 | flexcop_ibi_value v418, v41c; | ||
| 27 | v41c = fc->read_ibi_reg(fc, mac_address_41c); | ||
| 28 | |||
| 29 | v418.mac_address_418.MAC1 = mac[0]; | ||
| 30 | v418.mac_address_418.MAC2 = mac[1]; | ||
| 31 | v418.mac_address_418.MAC3 = mac[2]; | ||
| 32 | v418.mac_address_418.MAC6 = mac[3]; | ||
| 33 | v41c.mac_address_41c.MAC7 = mac[4]; | ||
| 34 | v41c.mac_address_41c.MAC8 = mac[5]; | ||
| 35 | |||
| 36 | fc->write_ibi_reg(fc, mac_address_418, v418); | ||
| 37 | fc->write_ibi_reg(fc, mac_address_41c, v41c); | ||
| 38 | } | ||
| 39 | |||
| 40 | void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff) | ||
| 41 | { | ||
| 42 | flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff); | ||
| 43 | } | ||
| 44 | |||
| 45 | static void flexcop_pid_group_filter(struct flexcop_device *fc, | ||
| 46 | u16 pid, u16 mask) | ||
| 47 | { | ||
| 48 | /* index_reg_310.extra_index_reg need to 0 or 7 to work */ | ||
| 49 | flexcop_ibi_value v30c; | ||
| 50 | v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid; | ||
| 51 | v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask; | ||
| 52 | fc->write_ibi_reg(fc, pid_filter_30c, v30c); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff) | ||
| 56 | { | ||
| 57 | flexcop_set_ibi_value(ctrl_208, Mask_filter_sig, onoff); | ||
| 58 | } | ||
| 59 | |||
| 60 | /* this fancy define reduces the code size of the quite similar PID controlling of | ||
| 61 | * the first 6 PIDs | ||
| 62 | */ | ||
| 63 | |||
| 64 | #define pid_ctrl(vregname,field,enablefield,trans_field,transval) \ | ||
| 65 | flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \ | ||
| 66 | v208 = fc->read_ibi_reg(fc, ctrl_208); \ | ||
| 67 | vpid.vregname.field = onoff ? pid : 0x1fff; \ | ||
| 68 | vpid.vregname.trans_field = transval; \ | ||
| 69 | v208.ctrl_208.enablefield = onoff; \ | ||
| 70 | fc->write_ibi_reg(fc, vregname, vpid); \ | ||
| 71 | fc->write_ibi_reg(fc, ctrl_208, v208); | ||
| 72 | |||
| 73 | static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, | ||
| 74 | u16 pid, int onoff) | ||
| 75 | { | ||
| 76 | pid_ctrl(pid_filter_300, Stream1_PID, Stream1_filter_sig, | ||
| 77 | Stream1_trans, 0); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, | ||
| 81 | u16 pid, int onoff) | ||
| 82 | { | ||
| 83 | pid_ctrl(pid_filter_300, Stream2_PID, Stream2_filter_sig, | ||
| 84 | Stream2_trans, 0); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, | ||
| 88 | u16 pid, int onoff) | ||
| 89 | { | ||
| 90 | pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0); | ||
| 91 | } | ||
| 92 | |||
| 93 | static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, | ||
| 94 | u16 pid, int onoff) | ||
| 95 | { | ||
| 96 | pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0); | ||
| 97 | } | ||
| 98 | |||
| 99 | static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, | ||
| 100 | u16 pid, int onoff) | ||
| 101 | { | ||
| 102 | pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, | ||
| 106 | u16 pid, int onoff) | ||
| 107 | { | ||
| 108 | pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void flexcop_pid_control(struct flexcop_device *fc, | ||
| 112 | int index, u16 pid, int onoff) | ||
| 113 | { | ||
| 114 | if (pid == 0x2000) | ||
| 115 | return; | ||
| 116 | |||
| 117 | deb_ts("setting pid: %5d %04x at index %d '%s'\n", | ||
| 118 | pid, pid, index, onoff ? "on" : "off"); | ||
| 119 | |||
| 120 | /* We could use bit magic here to reduce source code size. | ||
| 121 | * I decided against it, but to use the real register names */ | ||
| 122 | switch (index) { | ||
| 123 | case 0: | ||
| 124 | flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff); | ||
| 125 | break; | ||
| 126 | case 1: | ||
| 127 | flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff); | ||
| 128 | break; | ||
| 129 | case 2: | ||
| 130 | flexcop_pid_PCR_PID_ctrl(fc, pid, onoff); | ||
| 131 | break; | ||
| 132 | case 3: | ||
| 133 | flexcop_pid_PMT_PID_ctrl(fc, pid, onoff); | ||
| 134 | break; | ||
| 135 | case 4: | ||
| 136 | flexcop_pid_EMM_PID_ctrl(fc, pid, onoff); | ||
| 137 | break; | ||
| 138 | case 5: | ||
| 139 | flexcop_pid_ECM_PID_ctrl(fc, pid, onoff); | ||
| 140 | break; | ||
| 141 | default: | ||
| 142 | if (fc->has_32_hw_pid_filter && index < 38) { | ||
| 143 | flexcop_ibi_value vpid, vid; | ||
| 144 | |||
| 145 | /* set the index */ | ||
| 146 | vid = fc->read_ibi_reg(fc, index_reg_310); | ||
| 147 | vid.index_reg_310.index_reg = index - 6; | ||
| 148 | fc->write_ibi_reg(fc, index_reg_310, vid); | ||
| 149 | |||
| 150 | vpid = fc->read_ibi_reg(fc, pid_n_reg_314); | ||
| 151 | vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; | ||
| 152 | vpid.pid_n_reg_314.PID_enable_bit = onoff; | ||
| 153 | fc->write_ibi_reg(fc, pid_n_reg_314, vpid); | ||
| 154 | } | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff) | ||
| 160 | { | ||
| 161 | if (fc->fullts_streaming_state != onoff) { | ||
| 162 | deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling"); | ||
| 163 | flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff)); | ||
| 164 | flexcop_pid_group_filter_ctrl(fc, onoff); | ||
| 165 | fc->fullts_streaming_state = onoff; | ||
| 166 | } | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | int flexcop_pid_feed_control(struct flexcop_device *fc, | ||
| 171 | struct dvb_demux_feed *dvbdmxfeed, int onoff) | ||
| 172 | { | ||
| 173 | int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32; | ||
| 174 | |||
| 175 | fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */ | ||
| 176 | if (dvbdmxfeed->index >= max_pid_filter) | ||
| 177 | fc->extra_feedcount += onoff ? 1 : -1; | ||
| 178 | |||
| 179 | /* toggle complete-TS-streaming when: | ||
| 180 | * - pid_filtering is not enabled and it is the first or last feed requested | ||
| 181 | * - pid_filtering is enabled, | ||
| 182 | * - but the number of requested feeds is exceeded | ||
| 183 | * - or the requested pid is 0x2000 */ | ||
| 184 | |||
| 185 | if (!fc->pid_filtering && fc->feedcount == onoff) | ||
| 186 | flexcop_toggle_fullts_streaming(fc, onoff); | ||
| 187 | |||
| 188 | if (fc->pid_filtering) { | ||
| 189 | flexcop_pid_control \ | ||
| 190 | (fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff); | ||
| 191 | |||
| 192 | if (fc->extra_feedcount > 0) | ||
| 193 | flexcop_toggle_fullts_streaming(fc, 1); | ||
| 194 | else if (dvbdmxfeed->pid == 0x2000) | ||
| 195 | flexcop_toggle_fullts_streaming(fc, onoff); | ||
| 196 | else | ||
| 197 | flexcop_toggle_fullts_streaming(fc, 0); | ||
| 198 | } | ||
| 199 | |||
| 200 | /* if it was the first or last feed request change the stream-status */ | ||
| 201 | if (fc->feedcount == onoff) { | ||
| 202 | flexcop_rcv_data_ctrl(fc, onoff); | ||
| 203 | if (fc->stream_control) /* device specific stream control */ | ||
| 204 | fc->stream_control(fc, onoff); | ||
| 205 | |||
| 206 | /* feeding stopped -> reset the flexcop filter*/ | ||
| 207 | if (onoff == 0) { | ||
| 208 | flexcop_reset_block_300(fc); | ||
| 209 | flexcop_hw_filter_init(fc); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | EXPORT_SYMBOL(flexcop_pid_feed_control); | ||
| 215 | |||
| 216 | void flexcop_hw_filter_init(struct flexcop_device *fc) | ||
| 217 | { | ||
| 218 | int i; | ||
| 219 | flexcop_ibi_value v; | ||
| 220 | for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++) | ||
| 221 | flexcop_pid_control(fc, i, 0x1fff, 0); | ||
| 222 | |||
| 223 | flexcop_pid_group_filter(fc, 0, 0x1fe0); | ||
| 224 | flexcop_pid_group_filter_ctrl(fc, 0); | ||
| 225 | |||
| 226 | v = fc->read_ibi_reg(fc, pid_filter_308); | ||
| 227 | v.pid_filter_308.EMM_filter_4 = 1; | ||
| 228 | v.pid_filter_308.EMM_filter_6 = 0; | ||
| 229 | fc->write_ibi_reg(fc, pid_filter_308, v); | ||
| 230 | |||
| 231 | flexcop_null_filter_ctrl(fc, 1); | ||
| 232 | } | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c new file mode 100644 index 00000000000..965d5eb3375 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c | |||
| @@ -0,0 +1,288 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include "flexcop.h" | ||
| 7 | |||
| 8 | #define FC_MAX_I2C_RETRIES 100000 | ||
| 9 | |||
| 10 | static int flexcop_i2c_operation(struct flexcop_device *fc, | ||
| 11 | flexcop_ibi_value *r100) | ||
| 12 | { | ||
| 13 | int i; | ||
| 14 | flexcop_ibi_value r; | ||
| 15 | |||
| 16 | r100->tw_sm_c_100.working_start = 1; | ||
| 17 | deb_i2c("r100 before: %08x\n",r100->raw); | ||
| 18 | |||
| 19 | fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero); | ||
| 20 | fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */ | ||
| 21 | |||
| 22 | for (i = 0; i < FC_MAX_I2C_RETRIES; i++) { | ||
| 23 | r = fc->read_ibi_reg(fc, tw_sm_c_100); | ||
| 24 | |||
| 25 | if (!r.tw_sm_c_100.no_base_addr_ack_error) { | ||
| 26 | if (r.tw_sm_c_100.st_done) { | ||
| 27 | *r100 = r; | ||
| 28 | deb_i2c("i2c success\n"); | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | } else { | ||
| 32 | deb_i2c("suffering from an i2c ack_error\n"); | ||
| 33 | return -EREMOTEIO; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | deb_i2c("tried %d times i2c operation, " | ||
| 37 | "never finished or too many ack errors.\n", i); | ||
| 38 | return -EREMOTEIO; | ||
| 39 | } | ||
| 40 | |||
| 41 | static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, | ||
| 42 | flexcop_ibi_value r100, u8 *buf) | ||
| 43 | { | ||
| 44 | flexcop_ibi_value r104; | ||
| 45 | int len = r100.tw_sm_c_100.total_bytes, | ||
| 46 | /* remember total_bytes is buflen-1 */ | ||
| 47 | ret; | ||
| 48 | |||
| 49 | /* work-around to have CableStar2 and SkyStar2 rev 2.7 work | ||
| 50 | * correctly: | ||
| 51 | * | ||
| 52 | * the ITD1000 is behind an i2c-gate which closes automatically | ||
| 53 | * after an i2c-transaction the STV0297 needs 2 consecutive reads | ||
| 54 | * one with no_base_addr = 0 and one with 1 | ||
| 55 | * | ||
| 56 | * those two work-arounds are conflictin: we check for the card | ||
| 57 | * type, it is set when probing the ITD1000 */ | ||
| 58 | if (i2c->fc->dev_type == FC_SKY_REV27) | ||
| 59 | r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; | ||
| 60 | |||
| 61 | ret = flexcop_i2c_operation(i2c->fc, &r100); | ||
| 62 | if (ret != 0) { | ||
| 63 | deb_i2c("Retrying operation\n"); | ||
| 64 | r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; | ||
| 65 | ret = flexcop_i2c_operation(i2c->fc, &r100); | ||
| 66 | } | ||
| 67 | if (ret != 0) { | ||
| 68 | deb_i2c("read failed. %d\n", ret); | ||
| 69 | return ret; | ||
| 70 | } | ||
| 71 | |||
| 72 | buf[0] = r100.tw_sm_c_100.data1_reg; | ||
| 73 | |||
| 74 | if (len > 0) { | ||
| 75 | r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104); | ||
| 76 | deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw); | ||
| 77 | |||
| 78 | /* there is at least one more byte, otherwise we wouldn't be here */ | ||
| 79 | buf[1] = r104.tw_sm_c_104.data2_reg; | ||
| 80 | if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; | ||
| 81 | if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; | ||
| 82 | } | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static int flexcop_i2c_write4(struct flexcop_device *fc, | ||
| 87 | flexcop_ibi_value r100, u8 *buf) | ||
| 88 | { | ||
| 89 | flexcop_ibi_value r104; | ||
| 90 | int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */ | ||
| 91 | r104.raw = 0; | ||
| 92 | |||
| 93 | /* there is at least one byte, otherwise we wouldn't be here */ | ||
| 94 | r100.tw_sm_c_100.data1_reg = buf[0]; | ||
| 95 | r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0; | ||
| 96 | r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0; | ||
| 97 | r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0; | ||
| 98 | |||
| 99 | deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw); | ||
| 100 | |||
| 101 | /* write the additional i2c data before doing the actual i2c operation */ | ||
| 102 | fc->write_ibi_reg(fc, tw_sm_c_104, r104); | ||
| 103 | return flexcop_i2c_operation(fc, &r100); | ||
| 104 | } | ||
| 105 | |||
| 106 | int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c, | ||
| 107 | flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) | ||
| 108 | { | ||
| 109 | int ret; | ||
| 110 | |||
| 111 | #ifdef DUMP_I2C_MESSAGES | ||
| 112 | int i; | ||
| 113 | #endif | ||
| 114 | |||
| 115 | u16 bytes_to_transfer; | ||
| 116 | flexcop_ibi_value r100; | ||
| 117 | |||
| 118 | deb_i2c("op = %d\n",op); | ||
| 119 | r100.raw = 0; | ||
| 120 | r100.tw_sm_c_100.chipaddr = chipaddr; | ||
| 121 | r100.tw_sm_c_100.twoWS_rw = op; | ||
| 122 | r100.tw_sm_c_100.twoWS_port_reg = i2c->port; | ||
| 123 | |||
| 124 | #ifdef DUMP_I2C_MESSAGES | ||
| 125 | printk(KERN_DEBUG "%d ", i2c->port); | ||
| 126 | if (op == FC_READ) | ||
| 127 | printk("rd("); | ||
| 128 | else | ||
| 129 | printk("wr("); | ||
| 130 | printk("%02x): %02x ", chipaddr, addr); | ||
| 131 | #endif | ||
| 132 | |||
| 133 | /* in that case addr is the only value -> | ||
| 134 | * we write it twice as baseaddr and val0 | ||
| 135 | * BBTI is doing it like that for ISL6421 at least */ | ||
| 136 | if (i2c->no_base_addr && len == 0 && op == FC_WRITE) { | ||
| 137 | buf = &addr; | ||
| 138 | len = 1; | ||
| 139 | } | ||
| 140 | |||
| 141 | while (len != 0) { | ||
| 142 | bytes_to_transfer = len > 4 ? 4 : len; | ||
| 143 | |||
| 144 | r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1; | ||
| 145 | r100.tw_sm_c_100.baseaddr = addr; | ||
| 146 | |||
| 147 | if (op == FC_READ) | ||
| 148 | ret = flexcop_i2c_read4(i2c, r100, buf); | ||
| 149 | else | ||
| 150 | ret = flexcop_i2c_write4(i2c->fc, r100, buf); | ||
| 151 | |||
| 152 | #ifdef DUMP_I2C_MESSAGES | ||
| 153 | for (i = 0; i < bytes_to_transfer; i++) | ||
| 154 | printk("%02x ", buf[i]); | ||
| 155 | #endif | ||
| 156 | |||
| 157 | if (ret < 0) | ||
| 158 | return ret; | ||
| 159 | |||
| 160 | buf += bytes_to_transfer; | ||
| 161 | addr += bytes_to_transfer; | ||
| 162 | len -= bytes_to_transfer; | ||
| 163 | } | ||
| 164 | |||
| 165 | #ifdef DUMP_I2C_MESSAGES | ||
| 166 | printk("\n"); | ||
| 167 | #endif | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | /* exported for PCI i2c */ | ||
| 172 | EXPORT_SYMBOL(flexcop_i2c_request); | ||
| 173 | |||
| 174 | /* master xfer callback for demodulator */ | ||
| 175 | static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, | ||
| 176 | struct i2c_msg msgs[], int num) | ||
| 177 | { | ||
| 178 | struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); | ||
| 179 | int i, ret = 0; | ||
| 180 | |||
| 181 | /* Some drivers use 1 byte or 0 byte reads as probes, which this | ||
| 182 | * driver doesn't support. These probes will always fail, so this | ||
| 183 | * hack makes them always succeed. If one knew how, it would of | ||
| 184 | * course be better to actually do the read. */ | ||
| 185 | if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1) | ||
| 186 | return 1; | ||
| 187 | |||
| 188 | if (mutex_lock_interruptible(&i2c->fc->i2c_mutex)) | ||
| 189 | return -ERESTARTSYS; | ||
| 190 | |||
| 191 | for (i = 0; i < num; i++) { | ||
| 192 | /* reading */ | ||
| 193 | if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) { | ||
| 194 | ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr, | ||
| 195 | msgs[i].buf[0], msgs[i+1].buf, | ||
| 196 | msgs[i+1].len); | ||
| 197 | i++; /* skip the following message */ | ||
| 198 | } else /* writing */ | ||
| 199 | ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr, | ||
| 200 | msgs[i].buf[0], &msgs[i].buf[1], | ||
| 201 | msgs[i].len - 1); | ||
| 202 | if (ret < 0) { | ||
| 203 | deb_i2c("i2c master_xfer failed"); | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | mutex_unlock(&i2c->fc->i2c_mutex); | ||
| 209 | |||
| 210 | if (ret == 0) | ||
| 211 | ret = num; | ||
| 212 | return ret; | ||
| 213 | } | ||
| 214 | |||
| 215 | static u32 flexcop_i2c_func(struct i2c_adapter *adapter) | ||
| 216 | { | ||
| 217 | return I2C_FUNC_I2C; | ||
| 218 | } | ||
| 219 | |||
| 220 | static struct i2c_algorithm flexcop_algo = { | ||
| 221 | .master_xfer = flexcop_master_xfer, | ||
| 222 | .functionality = flexcop_i2c_func, | ||
| 223 | }; | ||
| 224 | |||
| 225 | int flexcop_i2c_init(struct flexcop_device *fc) | ||
| 226 | { | ||
| 227 | int ret; | ||
| 228 | mutex_init(&fc->i2c_mutex); | ||
| 229 | |||
| 230 | fc->fc_i2c_adap[0].fc = fc; | ||
| 231 | fc->fc_i2c_adap[1].fc = fc; | ||
| 232 | fc->fc_i2c_adap[2].fc = fc; | ||
| 233 | fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD; | ||
| 234 | fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; | ||
| 235 | fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; | ||
| 236 | |||
| 237 | strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod", | ||
| 238 | sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); | ||
| 239 | strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom", | ||
| 240 | sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); | ||
| 241 | strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner", | ||
| 242 | sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); | ||
| 243 | |||
| 244 | i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]); | ||
| 245 | i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]); | ||
| 246 | i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]); | ||
| 247 | |||
| 248 | fc->fc_i2c_adap[0].i2c_adap.algo = | ||
| 249 | fc->fc_i2c_adap[1].i2c_adap.algo = | ||
| 250 | fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo; | ||
| 251 | fc->fc_i2c_adap[0].i2c_adap.algo_data = | ||
| 252 | fc->fc_i2c_adap[1].i2c_adap.algo_data = | ||
| 253 | fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL; | ||
| 254 | fc->fc_i2c_adap[0].i2c_adap.dev.parent = | ||
| 255 | fc->fc_i2c_adap[1].i2c_adap.dev.parent = | ||
| 256 | fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev; | ||
| 257 | |||
| 258 | ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap); | ||
| 259 | if (ret < 0) | ||
| 260 | return ret; | ||
| 261 | |||
| 262 | ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap); | ||
| 263 | if (ret < 0) | ||
| 264 | goto adap_1_failed; | ||
| 265 | |||
| 266 | ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap); | ||
| 267 | if (ret < 0) | ||
| 268 | goto adap_2_failed; | ||
| 269 | |||
| 270 | fc->init_state |= FC_STATE_I2C_INIT; | ||
| 271 | return 0; | ||
| 272 | |||
| 273 | adap_2_failed: | ||
| 274 | i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); | ||
| 275 | adap_1_failed: | ||
| 276 | i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); | ||
| 277 | return ret; | ||
| 278 | } | ||
| 279 | |||
| 280 | void flexcop_i2c_exit(struct flexcop_device *fc) | ||
| 281 | { | ||
| 282 | if (fc->init_state & FC_STATE_I2C_INIT) { | ||
| 283 | i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap); | ||
| 284 | i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); | ||
| 285 | i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); | ||
| 286 | } | ||
| 287 | fc->init_state &= ~FC_STATE_I2C_INIT; | ||
| 288 | } | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c new file mode 100644 index 00000000000..f06f3a9070f --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-misc.c | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-misc.c - miscellaneous functions | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include "flexcop.h" | ||
| 7 | |||
| 8 | void flexcop_determine_revision(struct flexcop_device *fc) | ||
| 9 | { | ||
| 10 | flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); | ||
| 11 | |||
| 12 | switch (v.misc_204.Rev_N_sig_revision_hi) { | ||
| 13 | case 0x2: | ||
| 14 | deb_info("found a FlexCopII.\n"); | ||
| 15 | fc->rev = FLEXCOP_II; | ||
| 16 | break; | ||
| 17 | case 0x3: | ||
| 18 | deb_info("found a FlexCopIIb.\n"); | ||
| 19 | fc->rev = FLEXCOP_IIB; | ||
| 20 | break; | ||
| 21 | case 0x0: | ||
| 22 | deb_info("found a FlexCopIII.\n"); | ||
| 23 | fc->rev = FLEXCOP_III; | ||
| 24 | break; | ||
| 25 | default: | ||
| 26 | err("unknown FlexCop Revision: %x. Please report this to " | ||
| 27 | "linux-dvb@linuxtv.org.", | ||
| 28 | v.misc_204.Rev_N_sig_revision_hi); | ||
| 29 | break; | ||
| 30 | } | ||
| 31 | |||
| 32 | if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps)) | ||
| 33 | deb_info("this FlexCop has " | ||
| 34 | "the additional 32 hardware pid filter.\n"); | ||
| 35 | else | ||
| 36 | deb_info("this FlexCop has " | ||
| 37 | "the 6 basic main hardware pid filter.\n"); | ||
| 38 | /* bus parts have to decide if hw pid filtering is used or not. */ | ||
| 39 | } | ||
| 40 | |||
| 41 | static const char *flexcop_revision_names[] = { | ||
| 42 | "Unknown chip", | ||
| 43 | "FlexCopII", | ||
| 44 | "FlexCopIIb", | ||
| 45 | "FlexCopIII", | ||
| 46 | }; | ||
| 47 | |||
| 48 | static const char *flexcop_device_names[] = { | ||
| 49 | [FC_UNK] = "Unknown device", | ||
| 50 | [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C", | ||
| 51 | [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T", | ||
| 52 | [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation", | ||
| 53 | [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation", | ||
| 54 | [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", | ||
| 55 | [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)", | ||
| 56 | [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", | ||
| 57 | [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", | ||
| 58 | [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", | ||
| 59 | }; | ||
| 60 | |||
| 61 | static const char *flexcop_bus_names[] = { | ||
| 62 | "USB", | ||
| 63 | "PCI", | ||
| 64 | }; | ||
| 65 | |||
| 66 | void flexcop_device_name(struct flexcop_device *fc, | ||
| 67 | const char *prefix, const char *suffix) | ||
| 68 | { | ||
| 69 | info("%s '%s' at the '%s' bus controlled by a '%s' %s", | ||
| 70 | prefix, flexcop_device_names[fc->dev_type], | ||
| 71 | flexcop_bus_names[fc->bus_type], | ||
| 72 | flexcop_revision_names[fc->rev], suffix); | ||
| 73 | } | ||
| 74 | |||
| 75 | void flexcop_dump_reg(struct flexcop_device *fc, | ||
| 76 | flexcop_ibi_register reg, int num) | ||
| 77 | { | ||
| 78 | flexcop_ibi_value v; | ||
| 79 | int i; | ||
| 80 | for (i = 0; i < num; i++) { | ||
| 81 | v = fc->read_ibi_reg(fc, reg+4*i); | ||
| 82 | deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw); | ||
| 83 | } | ||
| 84 | deb_rdump("\n"); | ||
| 85 | } | ||
| 86 | EXPORT_SYMBOL(flexcop_dump_reg); | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c new file mode 100644 index 00000000000..44f8fb5f17f --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-pci.c | |||
| @@ -0,0 +1,450 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-pci.c - covers the PCI part including DMA transfers | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | |||
| 7 | #define FC_LOG_PREFIX "flexcop-pci" | ||
| 8 | #include "flexcop-common.h" | ||
| 9 | |||
| 10 | static int enable_pid_filtering = 1; | ||
| 11 | module_param(enable_pid_filtering, int, 0444); | ||
| 12 | MODULE_PARM_DESC(enable_pid_filtering, | ||
| 13 | "enable hardware pid filtering: supported values: 0 (fullts), 1"); | ||
| 14 | |||
| 15 | static int irq_chk_intv = 100; | ||
| 16 | module_param(irq_chk_intv, int, 0644); | ||
| 17 | MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); | ||
| 18 | |||
| 19 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | ||
| 20 | #define dprintk(level,args...) \ | ||
| 21 | do { if ((debug & level)) printk(args); } while (0) | ||
| 22 | #define DEBSTATUS "" | ||
| 23 | #else | ||
| 24 | #define dprintk(level,args...) | ||
| 25 | #define DEBSTATUS " (debugging is not enabled)" | ||
| 26 | #endif | ||
| 27 | |||
| 28 | #define deb_info(args...) dprintk(0x01, args) | ||
| 29 | #define deb_reg(args...) dprintk(0x02, args) | ||
| 30 | #define deb_ts(args...) dprintk(0x04, args) | ||
| 31 | #define deb_irq(args...) dprintk(0x08, args) | ||
| 32 | #define deb_chk(args...) dprintk(0x10, args) | ||
| 33 | |||
| 34 | static int debug; | ||
| 35 | module_param(debug, int, 0644); | ||
| 36 | MODULE_PARM_DESC(debug, | ||
| 37 | "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." | ||
| 38 | DEBSTATUS); | ||
| 39 | |||
| 40 | #define DRIVER_VERSION "0.1" | ||
| 41 | #define DRIVER_NAME "flexcop-pci" | ||
| 42 | #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>" | ||
| 43 | |||
| 44 | struct flexcop_pci { | ||
| 45 | struct pci_dev *pdev; | ||
| 46 | |||
| 47 | #define FC_PCI_INIT 0x01 | ||
| 48 | #define FC_PCI_DMA_INIT 0x02 | ||
| 49 | int init_state; | ||
| 50 | |||
| 51 | void __iomem *io_mem; | ||
| 52 | u32 irq; | ||
| 53 | /* buffersize (at least for DMA1, need to be % 188 == 0, | ||
| 54 | * this logic is required */ | ||
| 55 | #define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188) | ||
| 56 | #define FC_DEFAULT_DMA2_BUFSIZE (10 * 188) | ||
| 57 | struct flexcop_dma dma[2]; | ||
| 58 | |||
| 59 | int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ | ||
| 60 | u32 last_dma1_cur_pos; | ||
| 61 | /* position of the pointer last time the timer/packet irq occurred */ | ||
| 62 | int count; | ||
| 63 | int count_prev; | ||
| 64 | int stream_problem; | ||
| 65 | |||
| 66 | spinlock_t irq_lock; | ||
| 67 | unsigned long last_irq; | ||
| 68 | |||
| 69 | struct delayed_work irq_check_work; | ||
| 70 | struct flexcop_device *fc_dev; | ||
| 71 | }; | ||
| 72 | |||
| 73 | static int lastwreg, lastwval, lastrreg, lastrval; | ||
| 74 | |||
| 75 | static flexcop_ibi_value flexcop_pci_read_ibi_reg(struct flexcop_device *fc, | ||
| 76 | flexcop_ibi_register r) | ||
| 77 | { | ||
| 78 | struct flexcop_pci *fc_pci = fc->bus_specific; | ||
| 79 | flexcop_ibi_value v; | ||
| 80 | v.raw = readl(fc_pci->io_mem + r); | ||
| 81 | |||
| 82 | if (lastrreg != r || lastrval != v.raw) { | ||
| 83 | lastrreg = r; lastrval = v.raw; | ||
| 84 | deb_reg("new rd: %3x: %08x\n", r, v.raw); | ||
| 85 | } | ||
| 86 | |||
| 87 | return v; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, | ||
| 91 | flexcop_ibi_register r, flexcop_ibi_value v) | ||
| 92 | { | ||
| 93 | struct flexcop_pci *fc_pci = fc->bus_specific; | ||
| 94 | |||
| 95 | if (lastwreg != r || lastwval != v.raw) { | ||
| 96 | lastwreg = r; lastwval = v.raw; | ||
| 97 | deb_reg("new wr: %3x: %08x\n", r, v.raw); | ||
| 98 | } | ||
| 99 | |||
| 100 | writel(v.raw, fc_pci->io_mem + r); | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static void flexcop_pci_irq_check_work(struct work_struct *work) | ||
| 105 | { | ||
| 106 | struct flexcop_pci *fc_pci = | ||
| 107 | container_of(work, struct flexcop_pci, irq_check_work.work); | ||
| 108 | struct flexcop_device *fc = fc_pci->fc_dev; | ||
| 109 | |||
| 110 | if (fc->feedcount) { | ||
| 111 | |||
| 112 | if (fc_pci->count == fc_pci->count_prev) { | ||
| 113 | deb_chk("no IRQ since the last check\n"); | ||
| 114 | if (fc_pci->stream_problem++ == 3) { | ||
| 115 | struct dvb_demux_feed *feed; | ||
| 116 | deb_info("flexcop-pci: stream problem, resetting pid filter\n"); | ||
| 117 | |||
| 118 | spin_lock_irq(&fc->demux.lock); | ||
| 119 | list_for_each_entry(feed, &fc->demux.feed_list, | ||
| 120 | list_head) { | ||
| 121 | flexcop_pid_feed_control(fc, feed, 0); | ||
| 122 | } | ||
| 123 | |||
| 124 | list_for_each_entry(feed, &fc->demux.feed_list, | ||
| 125 | list_head) { | ||
| 126 | flexcop_pid_feed_control(fc, feed, 1); | ||
| 127 | } | ||
| 128 | spin_unlock_irq(&fc->demux.lock); | ||
| 129 | |||
| 130 | fc_pci->stream_problem = 0; | ||
| 131 | } | ||
| 132 | } else { | ||
| 133 | fc_pci->stream_problem = 0; | ||
| 134 | fc_pci->count_prev = fc_pci->count; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | schedule_delayed_work(&fc_pci->irq_check_work, | ||
| 139 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | ||
| 140 | } | ||
| 141 | |||
| 142 | /* When PID filtering is turned on, we use the timer IRQ, because small amounts | ||
| 143 | * of data need to be passed to the user space instantly as well. When PID | ||
| 144 | * filtering is turned off, we use the page-change-IRQ */ | ||
| 145 | static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) | ||
| 146 | { | ||
| 147 | struct flexcop_pci *fc_pci = dev_id; | ||
| 148 | struct flexcop_device *fc = fc_pci->fc_dev; | ||
| 149 | unsigned long flags; | ||
| 150 | flexcop_ibi_value v; | ||
| 151 | irqreturn_t ret = IRQ_HANDLED; | ||
| 152 | |||
| 153 | spin_lock_irqsave(&fc_pci->irq_lock, flags); | ||
| 154 | v = fc->read_ibi_reg(fc, irq_20c); | ||
| 155 | |||
| 156 | /* errors */ | ||
| 157 | if (v.irq_20c.Data_receiver_error) | ||
| 158 | deb_chk("data receiver error\n"); | ||
| 159 | if (v.irq_20c.Continuity_error_flag) | ||
| 160 | deb_chk("Contunuity error flag is set\n"); | ||
| 161 | if (v.irq_20c.LLC_SNAP_FLAG_set) | ||
| 162 | deb_chk("LLC_SNAP_FLAG_set is set\n"); | ||
| 163 | if (v.irq_20c.Transport_Error) | ||
| 164 | deb_chk("Transport error\n"); | ||
| 165 | |||
| 166 | if ((fc_pci->count % 1000) == 0) | ||
| 167 | deb_chk("%d valid irq took place so far\n", fc_pci->count); | ||
| 168 | |||
| 169 | if (v.irq_20c.DMA1_IRQ_Status == 1) { | ||
| 170 | if (fc_pci->active_dma1_addr == 0) | ||
| 171 | flexcop_pass_dmx_packets(fc_pci->fc_dev, | ||
| 172 | fc_pci->dma[0].cpu_addr0, | ||
| 173 | fc_pci->dma[0].size / 188); | ||
| 174 | else | ||
| 175 | flexcop_pass_dmx_packets(fc_pci->fc_dev, | ||
| 176 | fc_pci->dma[0].cpu_addr1, | ||
| 177 | fc_pci->dma[0].size / 188); | ||
| 178 | |||
| 179 | deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr); | ||
| 180 | fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr; | ||
| 181 | /* for the timer IRQ we only can use buffer dmx feeding, because we don't have | ||
| 182 | * complete TS packets when reading from the DMA memory */ | ||
| 183 | } else if (v.irq_20c.DMA1_Timer_Status == 1) { | ||
| 184 | dma_addr_t cur_addr = | ||
| 185 | fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; | ||
| 186 | u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; | ||
| 187 | |||
| 188 | deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, " | ||
| 189 | "last_cur_pos: %08x ", | ||
| 190 | jiffies_to_usecs(jiffies - fc_pci->last_irq), | ||
| 191 | v.raw, (unsigned long long)cur_addr, cur_pos, | ||
| 192 | fc_pci->last_dma1_cur_pos); | ||
| 193 | fc_pci->last_irq = jiffies; | ||
| 194 | |||
| 195 | /* buffer end was reached, restarted from the beginning | ||
| 196 | * pass the data from last_cur_pos to the buffer end to the demux | ||
| 197 | */ | ||
| 198 | if (cur_pos < fc_pci->last_dma1_cur_pos) { | ||
| 199 | deb_irq(" end was reached: passing %d bytes ", | ||
| 200 | (fc_pci->dma[0].size*2 - 1) - | ||
| 201 | fc_pci->last_dma1_cur_pos); | ||
| 202 | flexcop_pass_dmx_data(fc_pci->fc_dev, | ||
| 203 | fc_pci->dma[0].cpu_addr0 + | ||
| 204 | fc_pci->last_dma1_cur_pos, | ||
| 205 | (fc_pci->dma[0].size*2) - | ||
| 206 | fc_pci->last_dma1_cur_pos); | ||
| 207 | fc_pci->last_dma1_cur_pos = 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | if (cur_pos > fc_pci->last_dma1_cur_pos) { | ||
| 211 | deb_irq(" passing %d bytes ", | ||
| 212 | cur_pos - fc_pci->last_dma1_cur_pos); | ||
| 213 | flexcop_pass_dmx_data(fc_pci->fc_dev, | ||
| 214 | fc_pci->dma[0].cpu_addr0 + | ||
| 215 | fc_pci->last_dma1_cur_pos, | ||
| 216 | cur_pos - fc_pci->last_dma1_cur_pos); | ||
| 217 | } | ||
| 218 | deb_irq("\n"); | ||
| 219 | |||
| 220 | fc_pci->last_dma1_cur_pos = cur_pos; | ||
| 221 | fc_pci->count++; | ||
| 222 | } else { | ||
| 223 | deb_irq("isr for flexcop called, " | ||
| 224 | "apparently without reason (%08x)\n", v.raw); | ||
| 225 | ret = IRQ_NONE; | ||
| 226 | } | ||
| 227 | |||
| 228 | spin_unlock_irqrestore(&fc_pci->irq_lock, flags); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) | ||
| 233 | { | ||
| 234 | struct flexcop_pci *fc_pci = fc->bus_specific; | ||
| 235 | if (onoff) { | ||
| 236 | flexcop_dma_config(fc, &fc_pci->dma[0], FC_DMA_1); | ||
| 237 | flexcop_dma_config(fc, &fc_pci->dma[1], FC_DMA_2); | ||
| 238 | flexcop_dma_config_timer(fc, FC_DMA_1, 0); | ||
| 239 | flexcop_dma_xfer_control(fc, FC_DMA_1, | ||
| 240 | FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 1); | ||
| 241 | deb_irq("DMA xfer enabled\n"); | ||
| 242 | |||
| 243 | fc_pci->last_dma1_cur_pos = 0; | ||
| 244 | flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1); | ||
| 245 | deb_irq("IRQ enabled\n"); | ||
| 246 | fc_pci->count_prev = fc_pci->count; | ||
| 247 | } else { | ||
| 248 | flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0); | ||
| 249 | deb_irq("IRQ disabled\n"); | ||
| 250 | |||
| 251 | flexcop_dma_xfer_control(fc, FC_DMA_1, | ||
| 252 | FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 0); | ||
| 253 | deb_irq("DMA xfer disabled\n"); | ||
| 254 | } | ||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci) | ||
| 259 | { | ||
| 260 | int ret; | ||
| 261 | ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[0], | ||
| 262 | FC_DEFAULT_DMA1_BUFSIZE); | ||
| 263 | if (ret != 0) | ||
| 264 | return ret; | ||
| 265 | |||
| 266 | ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[1], | ||
| 267 | FC_DEFAULT_DMA2_BUFSIZE); | ||
| 268 | if (ret != 0) { | ||
| 269 | flexcop_dma_free(&fc_pci->dma[0]); | ||
| 270 | return ret; | ||
| 271 | } | ||
| 272 | |||
| 273 | flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_MEDIA | | ||
| 274 | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); | ||
| 275 | flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_CAO | | ||
| 276 | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); | ||
| 277 | fc_pci->init_state |= FC_PCI_DMA_INIT; | ||
| 278 | return ret; | ||
| 279 | } | ||
| 280 | |||
| 281 | static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci) | ||
| 282 | { | ||
| 283 | if (fc_pci->init_state & FC_PCI_DMA_INIT) { | ||
| 284 | flexcop_dma_free(&fc_pci->dma[0]); | ||
| 285 | flexcop_dma_free(&fc_pci->dma[1]); | ||
| 286 | } | ||
| 287 | fc_pci->init_state &= ~FC_PCI_DMA_INIT; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int flexcop_pci_init(struct flexcop_pci *fc_pci) | ||
| 291 | { | ||
| 292 | int ret; | ||
| 293 | |||
| 294 | info("card revision %x", fc_pci->pdev->revision); | ||
| 295 | |||
| 296 | if ((ret = pci_enable_device(fc_pci->pdev)) != 0) | ||
| 297 | return ret; | ||
| 298 | pci_set_master(fc_pci->pdev); | ||
| 299 | |||
| 300 | if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0) | ||
| 301 | goto err_pci_disable_device; | ||
| 302 | |||
| 303 | fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800); | ||
| 304 | |||
| 305 | if (!fc_pci->io_mem) { | ||
| 306 | err("cannot map io memory\n"); | ||
| 307 | ret = -EIO; | ||
| 308 | goto err_pci_release_regions; | ||
| 309 | } | ||
| 310 | |||
| 311 | pci_set_drvdata(fc_pci->pdev, fc_pci); | ||
| 312 | spin_lock_init(&fc_pci->irq_lock); | ||
| 313 | if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr, | ||
| 314 | IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) | ||
| 315 | goto err_pci_iounmap; | ||
| 316 | |||
| 317 | fc_pci->init_state |= FC_PCI_INIT; | ||
| 318 | return ret; | ||
| 319 | |||
| 320 | err_pci_iounmap: | ||
| 321 | pci_iounmap(fc_pci->pdev, fc_pci->io_mem); | ||
| 322 | pci_set_drvdata(fc_pci->pdev, NULL); | ||
| 323 | err_pci_release_regions: | ||
| 324 | pci_release_regions(fc_pci->pdev); | ||
| 325 | err_pci_disable_device: | ||
| 326 | pci_disable_device(fc_pci->pdev); | ||
| 327 | return ret; | ||
| 328 | } | ||
| 329 | |||
| 330 | static void flexcop_pci_exit(struct flexcop_pci *fc_pci) | ||
| 331 | { | ||
| 332 | if (fc_pci->init_state & FC_PCI_INIT) { | ||
| 333 | free_irq(fc_pci->pdev->irq, fc_pci); | ||
| 334 | pci_iounmap(fc_pci->pdev, fc_pci->io_mem); | ||
| 335 | pci_set_drvdata(fc_pci->pdev, NULL); | ||
| 336 | pci_release_regions(fc_pci->pdev); | ||
| 337 | pci_disable_device(fc_pci->pdev); | ||
| 338 | } | ||
| 339 | fc_pci->init_state &= ~FC_PCI_INIT; | ||
| 340 | } | ||
| 341 | |||
| 342 | static int flexcop_pci_probe(struct pci_dev *pdev, | ||
| 343 | const struct pci_device_id *ent) | ||
| 344 | { | ||
| 345 | struct flexcop_device *fc; | ||
| 346 | struct flexcop_pci *fc_pci; | ||
| 347 | int ret = -ENOMEM; | ||
| 348 | |||
| 349 | if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_pci))) == NULL) { | ||
| 350 | err("out of memory\n"); | ||
| 351 | return -ENOMEM; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* general flexcop init */ | ||
| 355 | fc_pci = fc->bus_specific; | ||
| 356 | fc_pci->fc_dev = fc; | ||
| 357 | |||
| 358 | fc->read_ibi_reg = flexcop_pci_read_ibi_reg; | ||
| 359 | fc->write_ibi_reg = flexcop_pci_write_ibi_reg; | ||
| 360 | fc->i2c_request = flexcop_i2c_request; | ||
| 361 | fc->get_mac_addr = flexcop_eeprom_check_mac_addr; | ||
| 362 | fc->stream_control = flexcop_pci_stream_control; | ||
| 363 | |||
| 364 | if (enable_pid_filtering) | ||
| 365 | info("will use the HW PID filter."); | ||
| 366 | else | ||
| 367 | info("will pass the complete TS to the demuxer."); | ||
| 368 | |||
| 369 | fc->pid_filtering = enable_pid_filtering; | ||
| 370 | fc->bus_type = FC_PCI; | ||
| 371 | fc->dev = &pdev->dev; | ||
| 372 | fc->owner = THIS_MODULE; | ||
| 373 | |||
| 374 | /* bus specific part */ | ||
| 375 | fc_pci->pdev = pdev; | ||
| 376 | if ((ret = flexcop_pci_init(fc_pci)) != 0) | ||
| 377 | goto err_kfree; | ||
| 378 | |||
| 379 | /* init flexcop */ | ||
| 380 | if ((ret = flexcop_device_initialize(fc)) != 0) | ||
| 381 | goto err_pci_exit; | ||
| 382 | |||
| 383 | /* init dma */ | ||
| 384 | if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) | ||
| 385 | goto err_fc_exit; | ||
| 386 | |||
| 387 | INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); | ||
| 388 | |||
| 389 | if (irq_chk_intv > 0) | ||
| 390 | schedule_delayed_work(&fc_pci->irq_check_work, | ||
| 391 | msecs_to_jiffies(irq_chk_intv < 100 ? | ||
| 392 | 100 : | ||
| 393 | irq_chk_intv)); | ||
| 394 | return ret; | ||
| 395 | |||
| 396 | err_fc_exit: | ||
| 397 | flexcop_device_exit(fc); | ||
| 398 | err_pci_exit: | ||
| 399 | flexcop_pci_exit(fc_pci); | ||
| 400 | err_kfree: | ||
| 401 | flexcop_device_kfree(fc); | ||
| 402 | return ret; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* in theory every _exit function should be called exactly two times, | ||
| 406 | * here and in the bail-out-part of the _init-function | ||
| 407 | */ | ||
| 408 | static void flexcop_pci_remove(struct pci_dev *pdev) | ||
| 409 | { | ||
| 410 | struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); | ||
| 411 | |||
| 412 | if (irq_chk_intv > 0) | ||
| 413 | cancel_delayed_work(&fc_pci->irq_check_work); | ||
| 414 | |||
| 415 | flexcop_pci_dma_exit(fc_pci); | ||
| 416 | flexcop_device_exit(fc_pci->fc_dev); | ||
| 417 | flexcop_pci_exit(fc_pci); | ||
| 418 | flexcop_device_kfree(fc_pci->fc_dev); | ||
| 419 | } | ||
| 420 | |||
| 421 | static struct pci_device_id flexcop_pci_tbl[] = { | ||
| 422 | { PCI_DEVICE(0x13d0, 0x2103) }, | ||
| 423 | { }, | ||
| 424 | }; | ||
| 425 | |||
| 426 | MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl); | ||
| 427 | |||
| 428 | static struct pci_driver flexcop_pci_driver = { | ||
| 429 | .name = "b2c2_flexcop_pci", | ||
| 430 | .id_table = flexcop_pci_tbl, | ||
| 431 | .probe = flexcop_pci_probe, | ||
| 432 | .remove = flexcop_pci_remove, | ||
| 433 | }; | ||
| 434 | |||
| 435 | static int __init flexcop_pci_module_init(void) | ||
| 436 | { | ||
| 437 | return pci_register_driver(&flexcop_pci_driver); | ||
| 438 | } | ||
| 439 | |||
| 440 | static void __exit flexcop_pci_module_exit(void) | ||
| 441 | { | ||
| 442 | pci_unregister_driver(&flexcop_pci_driver); | ||
| 443 | } | ||
| 444 | |||
| 445 | module_init(flexcop_pci_module_init); | ||
| 446 | module_exit(flexcop_pci_module_exit); | ||
| 447 | |||
| 448 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 449 | MODULE_DESCRIPTION(DRIVER_NAME); | ||
| 450 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h new file mode 100644 index 00000000000..dc4528dcbb9 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-reg.h | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #ifndef __FLEXCOP_REG_H__ | ||
| 7 | #define __FLEXCOP_REG_H__ | ||
| 8 | |||
| 9 | typedef enum { | ||
| 10 | FLEXCOP_UNK = 0, | ||
| 11 | FLEXCOP_II, | ||
| 12 | FLEXCOP_IIB, | ||
| 13 | FLEXCOP_III, | ||
| 14 | } flexcop_revision_t; | ||
| 15 | |||
| 16 | typedef enum { | ||
| 17 | FC_UNK = 0, | ||
| 18 | FC_CABLE, | ||
| 19 | FC_AIR_DVBT, | ||
| 20 | FC_AIR_ATSC1, | ||
| 21 | FC_AIR_ATSC2, | ||
| 22 | FC_AIR_ATSC3, | ||
| 23 | FC_SKY_REV23, | ||
| 24 | FC_SKY_REV26, | ||
| 25 | FC_SKY_REV27, | ||
| 26 | FC_SKY_REV28, | ||
| 27 | } flexcop_device_type_t; | ||
| 28 | |||
| 29 | typedef enum { | ||
| 30 | FC_USB = 0, | ||
| 31 | FC_PCI, | ||
| 32 | } flexcop_bus_t; | ||
| 33 | |||
| 34 | /* FlexCop IBI Registers */ | ||
| 35 | #if defined(__LITTLE_ENDIAN) | ||
| 36 | #include "flexcop_ibi_value_le.h" | ||
| 37 | #else | ||
| 38 | #if defined(__BIG_ENDIAN) | ||
| 39 | #include "flexcop_ibi_value_be.h" | ||
| 40 | #else | ||
| 41 | #error no endian defined | ||
| 42 | #endif | ||
| 43 | #endif | ||
| 44 | |||
| 45 | #define fc_data_Tag_ID_DVB 0x3e | ||
| 46 | #define fc_data_Tag_ID_ATSC 0x3f | ||
| 47 | #define fc_data_Tag_ID_IDSB 0x8b | ||
| 48 | |||
| 49 | #define fc_key_code_default 0x1 | ||
| 50 | #define fc_key_code_even 0x2 | ||
| 51 | #define fc_key_code_odd 0x3 | ||
| 52 | |||
| 53 | extern flexcop_ibi_value ibi_zero; | ||
| 54 | |||
| 55 | typedef enum { | ||
| 56 | FC_I2C_PORT_DEMOD = 1, | ||
| 57 | FC_I2C_PORT_EEPROM = 2, | ||
| 58 | FC_I2C_PORT_TUNER = 3, | ||
| 59 | } flexcop_i2c_port_t; | ||
| 60 | |||
| 61 | typedef enum { | ||
| 62 | FC_WRITE = 0, | ||
| 63 | FC_READ = 1, | ||
| 64 | } flexcop_access_op_t; | ||
| 65 | |||
| 66 | typedef enum { | ||
| 67 | FC_SRAM_DEST_NET = 1, | ||
| 68 | FC_SRAM_DEST_CAI = 2, | ||
| 69 | FC_SRAM_DEST_CAO = 4, | ||
| 70 | FC_SRAM_DEST_MEDIA = 8 | ||
| 71 | } flexcop_sram_dest_t; | ||
| 72 | |||
| 73 | typedef enum { | ||
| 74 | FC_SRAM_DEST_TARGET_WAN_USB = 0, | ||
| 75 | FC_SRAM_DEST_TARGET_DMA1 = 1, | ||
| 76 | FC_SRAM_DEST_TARGET_DMA2 = 2, | ||
| 77 | FC_SRAM_DEST_TARGET_FC3_CA = 3 | ||
| 78 | } flexcop_sram_dest_target_t; | ||
| 79 | |||
| 80 | typedef enum { | ||
| 81 | FC_SRAM_2_32KB = 0, /* 64KB */ | ||
| 82 | FC_SRAM_1_32KB = 1, /* 32KB - default fow FCII */ | ||
| 83 | FC_SRAM_1_128KB = 2, /* 128KB */ | ||
| 84 | FC_SRAM_1_48KB = 3, /* 48KB - default for FCIII */ | ||
| 85 | } flexcop_sram_type_t; | ||
| 86 | |||
| 87 | typedef enum { | ||
| 88 | FC_WAN_SPEED_4MBITS = 0, | ||
| 89 | FC_WAN_SPEED_8MBITS = 1, | ||
| 90 | FC_WAN_SPEED_12MBITS = 2, | ||
| 91 | FC_WAN_SPEED_16MBITS = 3, | ||
| 92 | } flexcop_wan_speed_t; | ||
| 93 | |||
| 94 | typedef enum { | ||
| 95 | FC_DMA_1 = 1, | ||
| 96 | FC_DMA_2 = 2, | ||
| 97 | } flexcop_dma_index_t; | ||
| 98 | |||
| 99 | typedef enum { | ||
| 100 | FC_DMA_SUBADDR_0 = 1, | ||
| 101 | FC_DMA_SUBADDR_1 = 2, | ||
| 102 | } flexcop_dma_addr_index_t; | ||
| 103 | |||
| 104 | /* names of the particular registers */ | ||
| 105 | typedef enum { | ||
| 106 | dma1_000 = 0x000, | ||
| 107 | dma1_004 = 0x004, | ||
| 108 | dma1_008 = 0x008, | ||
| 109 | dma1_00c = 0x00c, | ||
| 110 | dma2_010 = 0x010, | ||
| 111 | dma2_014 = 0x014, | ||
| 112 | dma2_018 = 0x018, | ||
| 113 | dma2_01c = 0x01c, | ||
| 114 | |||
| 115 | tw_sm_c_100 = 0x100, | ||
| 116 | tw_sm_c_104 = 0x104, | ||
| 117 | tw_sm_c_108 = 0x108, | ||
| 118 | tw_sm_c_10c = 0x10c, | ||
| 119 | tw_sm_c_110 = 0x110, | ||
| 120 | |||
| 121 | lnb_switch_freq_200 = 0x200, | ||
| 122 | misc_204 = 0x204, | ||
| 123 | ctrl_208 = 0x208, | ||
| 124 | irq_20c = 0x20c, | ||
| 125 | sw_reset_210 = 0x210, | ||
| 126 | misc_214 = 0x214, | ||
| 127 | mbox_v8_to_host_218 = 0x218, | ||
| 128 | mbox_host_to_v8_21c = 0x21c, | ||
| 129 | |||
| 130 | pid_filter_300 = 0x300, | ||
| 131 | pid_filter_304 = 0x304, | ||
| 132 | pid_filter_308 = 0x308, | ||
| 133 | pid_filter_30c = 0x30c, | ||
| 134 | index_reg_310 = 0x310, | ||
| 135 | pid_n_reg_314 = 0x314, | ||
| 136 | mac_low_reg_318 = 0x318, | ||
| 137 | mac_high_reg_31c = 0x31c, | ||
| 138 | |||
| 139 | data_tag_400 = 0x400, | ||
| 140 | card_id_408 = 0x408, | ||
| 141 | card_id_40c = 0x40c, | ||
| 142 | mac_address_418 = 0x418, | ||
| 143 | mac_address_41c = 0x41c, | ||
| 144 | |||
| 145 | ci_600 = 0x600, | ||
| 146 | pi_604 = 0x604, | ||
| 147 | pi_608 = 0x608, | ||
| 148 | dvb_reg_60c = 0x60c, | ||
| 149 | |||
| 150 | sram_ctrl_reg_700 = 0x700, | ||
| 151 | net_buf_reg_704 = 0x704, | ||
| 152 | cai_buf_reg_708 = 0x708, | ||
| 153 | cao_buf_reg_70c = 0x70c, | ||
| 154 | media_buf_reg_710 = 0x710, | ||
| 155 | sram_dest_reg_714 = 0x714, | ||
| 156 | net_buf_reg_718 = 0x718, | ||
| 157 | wan_ctrl_reg_71c = 0x71c, | ||
| 158 | } flexcop_ibi_register; | ||
| 159 | |||
| 160 | #define flexcop_set_ibi_value(reg,attr,val) { \ | ||
| 161 | flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \ | ||
| 162 | v.reg.attr = val; \ | ||
| 163 | fc->write_ibi_reg(fc,reg,v); \ | ||
| 164 | } | ||
| 165 | |||
| 166 | #endif | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c new file mode 100644 index 00000000000..f2199e43e80 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-sram.c | |||
| @@ -0,0 +1,363 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-sram.c - functions for controlling the SRAM | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #include "flexcop.h" | ||
| 7 | |||
| 8 | static void flexcop_sram_set_chip(struct flexcop_device *fc, | ||
| 9 | flexcop_sram_type_t type) | ||
| 10 | { | ||
| 11 | flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type); | ||
| 12 | } | ||
| 13 | |||
| 14 | int flexcop_sram_init(struct flexcop_device *fc) | ||
| 15 | { | ||
| 16 | switch (fc->rev) { | ||
| 17 | case FLEXCOP_II: | ||
| 18 | case FLEXCOP_IIB: | ||
| 19 | flexcop_sram_set_chip(fc, FC_SRAM_1_32KB); | ||
| 20 | break; | ||
| 21 | case FLEXCOP_III: | ||
| 22 | flexcop_sram_set_chip(fc, FC_SRAM_1_48KB); | ||
| 23 | break; | ||
| 24 | default: | ||
| 25 | return -EINVAL; | ||
| 26 | } | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, | ||
| 31 | flexcop_sram_dest_target_t target) | ||
| 32 | { | ||
| 33 | flexcop_ibi_value v; | ||
| 34 | v = fc->read_ibi_reg(fc, sram_dest_reg_714); | ||
| 35 | |||
| 36 | if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) { | ||
| 37 | err("SRAM destination target to available on FlexCopII(b)\n"); | ||
| 38 | return -EINVAL; | ||
| 39 | } | ||
| 40 | deb_sram("sram dest: %x target: %x\n", dest, target); | ||
| 41 | |||
| 42 | if (dest & FC_SRAM_DEST_NET) | ||
| 43 | v.sram_dest_reg_714.NET_Dest = target; | ||
| 44 | if (dest & FC_SRAM_DEST_CAI) | ||
| 45 | v.sram_dest_reg_714.CAI_Dest = target; | ||
| 46 | if (dest & FC_SRAM_DEST_CAO) | ||
| 47 | v.sram_dest_reg_714.CAO_Dest = target; | ||
| 48 | if (dest & FC_SRAM_DEST_MEDIA) | ||
| 49 | v.sram_dest_reg_714.MEDIA_Dest = target; | ||
| 50 | |||
| 51 | fc->write_ibi_reg(fc,sram_dest_reg_714,v); | ||
| 52 | udelay(1000); /* TODO delay really necessary */ | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | EXPORT_SYMBOL(flexcop_sram_set_dest); | ||
| 57 | |||
| 58 | void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s) | ||
| 59 | { | ||
| 60 | flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s); | ||
| 61 | } | ||
| 62 | EXPORT_SYMBOL(flexcop_wan_set_speed); | ||
| 63 | |||
| 64 | void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill) | ||
| 65 | { | ||
| 66 | flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); | ||
| 67 | v.sram_dest_reg_714.ctrl_usb_wan = usb_wan; | ||
| 68 | v.sram_dest_reg_714.ctrl_sramdma = sramdma; | ||
| 69 | v.sram_dest_reg_714.ctrl_maximumfill = maximumfill; | ||
| 70 | fc->write_ibi_reg(fc,sram_dest_reg_714,v); | ||
| 71 | } | ||
| 72 | EXPORT_SYMBOL(flexcop_sram_ctrl); | ||
| 73 | |||
| 74 | #if 0 | ||
| 75 | static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len) | ||
| 76 | { | ||
| 77 | int i, retries; | ||
| 78 | u32 command; | ||
| 79 | |||
| 80 | for (i = 0; i < len; i++) { | ||
| 81 | command = bank | addr | 0x04000000 | (*buf << 0x10); | ||
| 82 | |||
| 83 | retries = 2; | ||
| 84 | |||
| 85 | while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { | ||
| 86 | mdelay(1); | ||
| 87 | retries--; | ||
| 88 | }; | ||
| 89 | |||
| 90 | if (retries == 0) | ||
| 91 | printk("%s: SRAM timeout\n", __func__); | ||
| 92 | |||
| 93 | write_reg_dw(adapter, 0x700, command); | ||
| 94 | |||
| 95 | buf++; | ||
| 96 | addr++; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len) | ||
| 101 | { | ||
| 102 | int i, retries; | ||
| 103 | u32 command, value; | ||
| 104 | |||
| 105 | for (i = 0; i < len; i++) { | ||
| 106 | command = bank | addr | 0x04008000; | ||
| 107 | |||
| 108 | retries = 10000; | ||
| 109 | |||
| 110 | while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { | ||
| 111 | mdelay(1); | ||
| 112 | retries--; | ||
| 113 | }; | ||
| 114 | |||
| 115 | if (retries == 0) | ||
| 116 | printk("%s: SRAM timeout\n", __func__); | ||
| 117 | |||
| 118 | write_reg_dw(adapter, 0x700, command); | ||
| 119 | |||
| 120 | retries = 10000; | ||
| 121 | |||
| 122 | while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { | ||
| 123 | mdelay(1); | ||
| 124 | retries--; | ||
| 125 | }; | ||
| 126 | |||
| 127 | if (retries == 0) | ||
| 128 | printk("%s: SRAM timeout\n", __func__); | ||
| 129 | |||
| 130 | value = read_reg_dw(adapter, 0x700) >> 0x10; | ||
| 131 | |||
| 132 | *buf = (value & 0xff); | ||
| 133 | |||
| 134 | addr++; | ||
| 135 | buf++; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) | ||
| 140 | { | ||
| 141 | u32 bank; | ||
| 142 | |||
| 143 | bank = 0; | ||
| 144 | |||
| 145 | if (adapter->dw_sram_type == 0x20000) { | ||
| 146 | bank = (addr & 0x18000) << 0x0d; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (adapter->dw_sram_type == 0x00000) { | ||
| 150 | if ((addr >> 0x0f) == 0) | ||
| 151 | bank = 0x20000000; | ||
| 152 | else | ||
| 153 | bank = 0x10000000; | ||
| 154 | } | ||
| 155 | flex_sram_write(adapter, bank, addr & 0x7fff, buf, len); | ||
| 156 | } | ||
| 157 | |||
| 158 | static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) | ||
| 159 | { | ||
| 160 | u32 bank; | ||
| 161 | bank = 0; | ||
| 162 | |||
| 163 | if (adapter->dw_sram_type == 0x20000) { | ||
| 164 | bank = (addr & 0x18000) << 0x0d; | ||
| 165 | } | ||
| 166 | |||
| 167 | if (adapter->dw_sram_type == 0x00000) { | ||
| 168 | if ((addr >> 0x0f) == 0) | ||
| 169 | bank = 0x20000000; | ||
| 170 | else | ||
| 171 | bank = 0x10000000; | ||
| 172 | } | ||
| 173 | flex_sram_read(adapter, bank, addr & 0x7fff, buf, len); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len) | ||
| 177 | { | ||
| 178 | u32 length; | ||
| 179 | while (len != 0) { | ||
| 180 | length = len; | ||
| 181 | /* check if the address range belongs to the same | ||
| 182 | * 32K memory chip. If not, the data is read | ||
| 183 | * from one chip at a time */ | ||
| 184 | if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { | ||
| 185 | length = (((addr >> 0x0f) + 1) << 0x0f) - addr; | ||
| 186 | } | ||
| 187 | |||
| 188 | sram_read_chunk(adapter, addr, buf, length); | ||
| 189 | addr = addr + length; | ||
| 190 | buf = buf + length; | ||
| 191 | len = len - length; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len) | ||
| 196 | { | ||
| 197 | u32 length; | ||
| 198 | while (len != 0) { | ||
| 199 | length = len; | ||
| 200 | |||
| 201 | /* check if the address range belongs to the same | ||
| 202 | * 32K memory chip. If not, the data is | ||
| 203 | * written to one chip at a time */ | ||
| 204 | if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { | ||
| 205 | length = (((addr >> 0x0f) + 1) << 0x0f) - addr; | ||
| 206 | } | ||
| 207 | |||
| 208 | sram_write_chunk(adapter, addr, buf, length); | ||
| 209 | addr = addr + length; | ||
| 210 | buf = buf + length; | ||
| 211 | len = len - length; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | static void sram_set_size(struct adapter *adapter, u32 mask) | ||
| 216 | { | ||
| 217 | write_reg_dw(adapter, 0x71c, | ||
| 218 | (mask | (~0x30000 & read_reg_dw(adapter, 0x71c)))); | ||
| 219 | } | ||
| 220 | |||
| 221 | static void sram_init(struct adapter *adapter) | ||
| 222 | { | ||
| 223 | u32 tmp; | ||
| 224 | tmp = read_reg_dw(adapter, 0x71c); | ||
| 225 | write_reg_dw(adapter, 0x71c, 1); | ||
| 226 | |||
| 227 | if (read_reg_dw(adapter, 0x71c) != 0) { | ||
| 228 | write_reg_dw(adapter, 0x71c, tmp); | ||
| 229 | adapter->dw_sram_type = tmp & 0x30000; | ||
| 230 | ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); | ||
| 231 | } else { | ||
| 232 | adapter->dw_sram_type = 0x10000; | ||
| 233 | ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) | ||
| 238 | { | ||
| 239 | u8 tmp1, tmp2; | ||
| 240 | dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr); | ||
| 241 | |||
| 242 | sram_set_size(adapter, mask); | ||
| 243 | sram_init(adapter); | ||
| 244 | |||
| 245 | tmp2 = 0xa5; | ||
| 246 | tmp1 = 0x4f; | ||
| 247 | |||
| 248 | sram_write(adapter, addr, &tmp2, 1); | ||
| 249 | sram_write(adapter, addr + 4, &tmp1, 1); | ||
| 250 | |||
| 251 | tmp2 = 0; | ||
| 252 | mdelay(20); | ||
| 253 | |||
| 254 | sram_read(adapter, addr, &tmp2, 1); | ||
| 255 | sram_read(adapter, addr, &tmp2, 1); | ||
| 256 | |||
| 257 | dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2); | ||
| 258 | |||
| 259 | if (tmp2 != 0xa5) | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | tmp2 = 0x5a; | ||
| 263 | tmp1 = 0xf4; | ||
| 264 | |||
| 265 | sram_write(adapter, addr, &tmp2, 1); | ||
| 266 | sram_write(adapter, addr + 4, &tmp1, 1); | ||
| 267 | |||
| 268 | tmp2 = 0; | ||
| 269 | mdelay(20); | ||
| 270 | |||
| 271 | sram_read(adapter, addr, &tmp2, 1); | ||
| 272 | sram_read(adapter, addr, &tmp2, 1); | ||
| 273 | |||
| 274 | dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2); | ||
| 275 | |||
| 276 | if (tmp2 != 0x5a) | ||
| 277 | return 0; | ||
| 278 | return 1; | ||
| 279 | } | ||
| 280 | |||
| 281 | static u32 sram_length(struct adapter *adapter) | ||
| 282 | { | ||
| 283 | if (adapter->dw_sram_type == 0x10000) | ||
| 284 | return 32768; /* 32K */ | ||
| 285 | if (adapter->dw_sram_type == 0x00000) | ||
| 286 | return 65536; /* 64K */ | ||
| 287 | if (adapter->dw_sram_type == 0x20000) | ||
| 288 | return 131072; /* 128K */ | ||
| 289 | return 32768; /* 32K */ | ||
| 290 | } | ||
| 291 | |||
| 292 | /* FlexcopII can work with 32K, 64K or 128K of external SRAM memory. | ||
| 293 | - for 128K there are 4x32K chips at bank 0,1,2,3. | ||
| 294 | - for 64K there are 2x32K chips at bank 1,2. | ||
| 295 | - for 32K there is one 32K chip at bank 0. | ||
| 296 | |||
| 297 | FlexCop works only with one bank at a time. The bank is selected | ||
| 298 | by bits 28-29 of the 0x700 register. | ||
| 299 | |||
| 300 | bank 0 covers addresses 0x00000-0x07fff | ||
| 301 | bank 1 covers addresses 0x08000-0x0ffff | ||
| 302 | bank 2 covers addresses 0x10000-0x17fff | ||
| 303 | bank 3 covers addresses 0x18000-0x1ffff */ | ||
| 304 | |||
| 305 | static int flexcop_sram_detect(struct flexcop_device *fc) | ||
| 306 | { | ||
| 307 | flexcop_ibi_value r208, r71c_0, vr71c_1; | ||
| 308 | r208 = fc->read_ibi_reg(fc, ctrl_208); | ||
| 309 | fc->write_ibi_reg(fc, ctrl_208, ibi_zero); | ||
| 310 | |||
| 311 | r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c); | ||
| 312 | write_reg_dw(adapter, 0x71c, 1); | ||
| 313 | tmp3 = read_reg_dw(adapter, 0x71c); | ||
| 314 | dprintk("%s: tmp3 = %x\n", __func__, tmp3); | ||
| 315 | write_reg_dw(adapter, 0x71c, tmp2); | ||
| 316 | |||
| 317 | // check for internal SRAM ??? | ||
| 318 | tmp3--; | ||
| 319 | if (tmp3 != 0) { | ||
| 320 | sram_set_size(adapter, 0x10000); | ||
| 321 | sram_init(adapter); | ||
| 322 | write_reg_dw(adapter, 0x208, tmp); | ||
| 323 | dprintk("%s: sram size = 32K\n", __func__); | ||
| 324 | return 32; | ||
| 325 | } | ||
| 326 | |||
| 327 | if (sram_test_location(adapter, 0x20000, 0x18000) != 0) { | ||
| 328 | sram_set_size(adapter, 0x20000); | ||
| 329 | sram_init(adapter); | ||
| 330 | write_reg_dw(adapter, 0x208, tmp); | ||
| 331 | dprintk("%s: sram size = 128K\n", __func__); | ||
| 332 | return 128; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (sram_test_location(adapter, 0x00000, 0x10000) != 0) { | ||
| 336 | sram_set_size(adapter, 0x00000); | ||
| 337 | sram_init(adapter); | ||
| 338 | write_reg_dw(adapter, 0x208, tmp); | ||
| 339 | dprintk("%s: sram size = 64K\n", __func__); | ||
| 340 | return 64; | ||
| 341 | } | ||
| 342 | |||
| 343 | if (sram_test_location(adapter, 0x10000, 0x00000) != 0) { | ||
| 344 | sram_set_size(adapter, 0x10000); | ||
| 345 | sram_init(adapter); | ||
| 346 | write_reg_dw(adapter, 0x208, tmp); | ||
| 347 | dprintk("%s: sram size = 32K\n", __func__); | ||
| 348 | return 32; | ||
| 349 | } | ||
| 350 | |||
| 351 | sram_set_size(adapter, 0x10000); | ||
| 352 | sram_init(adapter); | ||
| 353 | write_reg_dw(adapter, 0x208, tmp); | ||
| 354 | dprintk("%s: SRAM detection failed. Set to 32K \n", __func__); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void sll_detect_sram_size(struct adapter *adapter) | ||
| 359 | { | ||
| 360 | sram_detect_for_flex2(adapter); | ||
| 361 | } | ||
| 362 | |||
| 363 | #endif | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c new file mode 100644 index 00000000000..bedcfb67162 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-usb.c | |||
| @@ -0,0 +1,608 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-usb.c - covers the USB part | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #define FC_LOG_PREFIX "flexcop_usb" | ||
| 7 | #include "flexcop-usb.h" | ||
| 8 | #include "flexcop-common.h" | ||
| 9 | |||
| 10 | /* Version information */ | ||
| 11 | #define DRIVER_VERSION "0.1" | ||
| 12 | #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver" | ||
| 13 | #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>" | ||
| 14 | |||
| 15 | /* debug */ | ||
| 16 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | ||
| 17 | #define dprintk(level,args...) \ | ||
| 18 | do { if ((debug & level)) printk(args); } while (0) | ||
| 19 | |||
| 20 | #define debug_dump(b, l, method) do {\ | ||
| 21 | int i; \ | ||
| 22 | for (i = 0; i < l; i++) \ | ||
| 23 | method("%02x ", b[i]); \ | ||
| 24 | method("\n"); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | #define DEBSTATUS "" | ||
| 28 | #else | ||
| 29 | #define dprintk(level, args...) | ||
| 30 | #define debug_dump(b, l, method) | ||
| 31 | #define DEBSTATUS " (debugging is not enabled)" | ||
| 32 | #endif | ||
| 33 | |||
| 34 | static int debug; | ||
| 35 | module_param(debug, int, 0644); | ||
| 36 | MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2," | ||
| 37 | "ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS); | ||
| 38 | #undef DEBSTATUS | ||
| 39 | |||
| 40 | #define deb_info(args...) dprintk(0x01, args) | ||
| 41 | #define deb_ts(args...) dprintk(0x02, args) | ||
| 42 | #define deb_ctrl(args...) dprintk(0x04, args) | ||
| 43 | #define deb_i2c(args...) dprintk(0x08, args) | ||
| 44 | #define deb_v8(args...) dprintk(0x10, args) | ||
| 45 | |||
| 46 | /* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits | ||
| 47 | * in the IBI address, to make the V8 code simpler. | ||
| 48 | * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (the six bits used) | ||
| 49 | * in general: 0000 0HHH 000L LL00 | ||
| 50 | * IBI ADDRESS FORMAT: RHHH BLLL | ||
| 51 | * | ||
| 52 | * where R is the read(1)/write(0) bit, B is the busy bit | ||
| 53 | * and HHH and LLL are the two sets of three bits from the PCI address. | ||
| 54 | */ | ||
| 55 | #define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \ | ||
| 56 | (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70)) | ||
| 57 | #define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \ | ||
| 58 | (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4)) | ||
| 59 | |||
| 60 | /* | ||
| 61 | * DKT 020228 | ||
| 62 | * - forget about this VENDOR_BUFFER_SIZE, read and write register | ||
| 63 | * deal with DWORD or 4 bytes, that should be should from now on | ||
| 64 | * - from now on, we don't support anything older than firm 1.00 | ||
| 65 | * I eliminated the write register as a 2 trip of writing hi word and lo word | ||
| 66 | * and force this to write only 4 bytes at a time. | ||
| 67 | * NOTE: this should work with all the firmware from 1.00 and newer | ||
| 68 | */ | ||
| 69 | static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, u32 *val, u8 read) | ||
| 70 | { | ||
| 71 | struct flexcop_usb *fc_usb = fc->bus_specific; | ||
| 72 | u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG; | ||
| 73 | u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; | ||
| 74 | u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | | ||
| 75 | (read ? 0x80 : 0); | ||
| 76 | |||
| 77 | int len = usb_control_msg(fc_usb->udev, | ||
| 78 | read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, | ||
| 79 | request, | ||
| 80 | request_type, /* 0xc0 read or 0x40 write */ | ||
| 81 | wAddress, | ||
| 82 | 0, | ||
| 83 | val, | ||
| 84 | sizeof(u32), | ||
| 85 | B2C2_WAIT_FOR_OPERATION_RDW * HZ); | ||
| 86 | |||
| 87 | if (len != sizeof(u32)) { | ||
| 88 | err("error while %s dword from %d (%d).", read ? "reading" : | ||
| 89 | "writing", wAddress, wRegOffsPCI); | ||
| 90 | return -EIO; | ||
| 91 | } | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | /* | ||
| 95 | * DKT 010817 - add support for V8 memory read/write and flash update | ||
| 96 | */ | ||
| 97 | static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, | ||
| 98 | flexcop_usb_request_t req, u8 page, u16 wAddress, | ||
| 99 | u8 *pbBuffer, u32 buflen) | ||
| 100 | { | ||
| 101 | u8 request_type = USB_TYPE_VENDOR; | ||
| 102 | u16 wIndex; | ||
| 103 | int nWaitTime, pipe, len; | ||
| 104 | wIndex = page << 8; | ||
| 105 | |||
| 106 | switch (req) { | ||
| 107 | case B2C2_USB_READ_V8_MEM: | ||
| 108 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; | ||
| 109 | request_type |= USB_DIR_IN; | ||
| 110 | pipe = B2C2_USB_CTRL_PIPE_IN; | ||
| 111 | break; | ||
| 112 | case B2C2_USB_WRITE_V8_MEM: | ||
| 113 | wIndex |= pbBuffer[0]; | ||
| 114 | request_type |= USB_DIR_OUT; | ||
| 115 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE; | ||
| 116 | pipe = B2C2_USB_CTRL_PIPE_OUT; | ||
| 117 | break; | ||
| 118 | case B2C2_USB_FLASH_BLOCK: | ||
| 119 | request_type |= USB_DIR_OUT; | ||
| 120 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH; | ||
| 121 | pipe = B2C2_USB_CTRL_PIPE_OUT; | ||
| 122 | break; | ||
| 123 | default: | ||
| 124 | deb_info("unsupported request for v8_mem_req %x.\n", req); | ||
| 125 | return -EINVAL; | ||
| 126 | } | ||
| 127 | deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, | ||
| 128 | wAddress, wIndex, buflen); | ||
| 129 | |||
| 130 | len = usb_control_msg(fc_usb->udev, pipe, | ||
| 131 | req, | ||
| 132 | request_type, | ||
| 133 | wAddress, | ||
| 134 | wIndex, | ||
| 135 | pbBuffer, | ||
| 136 | buflen, | ||
| 137 | nWaitTime * HZ); | ||
| 138 | |||
| 139 | debug_dump(pbBuffer, len, deb_v8); | ||
| 140 | return len == buflen ? 0 : -EIO; | ||
| 141 | } | ||
| 142 | |||
| 143 | #define bytes_left_to_read_on_page(paddr,buflen) \ | ||
| 144 | ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ | ||
| 145 | ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK))) | ||
| 146 | |||
| 147 | static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb, | ||
| 148 | flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start, | ||
| 149 | u32 addr, int extended, u8 *buf, u32 len) | ||
| 150 | { | ||
| 151 | int i,ret = 0; | ||
| 152 | u16 wMax; | ||
| 153 | u32 pagechunk = 0; | ||
| 154 | |||
| 155 | switch(req) { | ||
| 156 | case B2C2_USB_READ_V8_MEM: | ||
| 157 | wMax = USB_MEM_READ_MAX; | ||
| 158 | break; | ||
| 159 | case B2C2_USB_WRITE_V8_MEM: | ||
| 160 | wMax = USB_MEM_WRITE_MAX; | ||
| 161 | break; | ||
| 162 | case B2C2_USB_FLASH_BLOCK: | ||
| 163 | wMax = USB_FLASH_MAX; | ||
| 164 | break; | ||
| 165 | default: | ||
| 166 | return -EINVAL; | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | for (i = 0; i < len;) { | ||
| 170 | pagechunk = | ||
| 171 | wMax < bytes_left_to_read_on_page(addr, len) ? | ||
| 172 | wMax : | ||
| 173 | bytes_left_to_read_on_page(addr, len); | ||
| 174 | deb_info("%x\n", | ||
| 175 | (addr & V8_MEMORY_PAGE_MASK) | | ||
| 176 | (V8_MEMORY_EXTENDED*extended)); | ||
| 177 | |||
| 178 | ret = flexcop_usb_v8_memory_req(fc_usb, req, | ||
| 179 | page_start + (addr / V8_MEMORY_PAGE_SIZE), | ||
| 180 | (addr & V8_MEMORY_PAGE_MASK) | | ||
| 181 | (V8_MEMORY_EXTENDED*extended), | ||
| 182 | &buf[i], pagechunk); | ||
| 183 | |||
| 184 | if (ret < 0) | ||
| 185 | return ret; | ||
| 186 | addr += pagechunk; | ||
| 187 | len -= pagechunk; | ||
| 188 | } | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended) | ||
| 193 | { | ||
| 194 | return flexcop_usb_memory_req(fc->bus_specific, B2C2_USB_READ_V8_MEM, | ||
| 195 | V8_MEMORY_PAGE_FLASH, 0x1f010, 1, | ||
| 196 | fc->dvb_adapter.proposed_mac, 6); | ||
| 197 | } | ||
| 198 | |||
| 199 | #if 0 | ||
| 200 | static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, | ||
| 201 | flexcop_usb_utility_function_t func, u8 extra, u16 wIndex, | ||
| 202 | u16 buflen, u8 *pvBuffer) | ||
| 203 | { | ||
| 204 | u16 wValue; | ||
| 205 | u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; | ||
| 206 | int nWaitTime = 2, | ||
| 207 | pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len; | ||
| 208 | wValue = (func << 8) | extra; | ||
| 209 | |||
| 210 | len = usb_control_msg(fc_usb->udev,pipe, | ||
| 211 | B2C2_USB_UTILITY, | ||
| 212 | request_type, | ||
| 213 | wValue, | ||
| 214 | wIndex, | ||
| 215 | pvBuffer, | ||
| 216 | buflen, | ||
| 217 | nWaitTime * HZ); | ||
| 218 | return len == buflen ? 0 : -EIO; | ||
| 219 | } | ||
| 220 | #endif | ||
| 221 | |||
| 222 | /* usb i2c stuff */ | ||
| 223 | static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, | ||
| 224 | flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, | ||
| 225 | u8 chipaddr, u8 addr, u8 *buf, u8 buflen) | ||
| 226 | { | ||
| 227 | struct flexcop_usb *fc_usb = i2c->fc->bus_specific; | ||
| 228 | u16 wValue, wIndex; | ||
| 229 | int nWaitTime,pipe,len; | ||
| 230 | u8 request_type = USB_TYPE_VENDOR; | ||
| 231 | |||
| 232 | switch (func) { | ||
| 233 | case USB_FUNC_I2C_WRITE: | ||
| 234 | case USB_FUNC_I2C_MULTIWRITE: | ||
| 235 | case USB_FUNC_I2C_REPEATWRITE: | ||
| 236 | /* DKT 020208 - add this to support special case of DiSEqC */ | ||
| 237 | case USB_FUNC_I2C_CHECKWRITE: | ||
| 238 | pipe = B2C2_USB_CTRL_PIPE_OUT; | ||
| 239 | nWaitTime = 2; | ||
| 240 | request_type |= USB_DIR_OUT; | ||
| 241 | break; | ||
| 242 | case USB_FUNC_I2C_READ: | ||
| 243 | case USB_FUNC_I2C_REPEATREAD: | ||
| 244 | pipe = B2C2_USB_CTRL_PIPE_IN; | ||
| 245 | nWaitTime = 2; | ||
| 246 | request_type |= USB_DIR_IN; | ||
| 247 | break; | ||
| 248 | default: | ||
| 249 | deb_info("unsupported function for i2c_req %x\n", func); | ||
| 250 | return -EINVAL; | ||
| 251 | } | ||
| 252 | wValue = (func << 8) | (i2c->port << 4); | ||
| 253 | wIndex = (chipaddr << 8 ) | addr; | ||
| 254 | |||
| 255 | deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n", | ||
| 256 | func, request_type, req, | ||
| 257 | wValue & 0xff, wValue >> 8, | ||
| 258 | wIndex & 0xff, wIndex >> 8); | ||
| 259 | |||
| 260 | len = usb_control_msg(fc_usb->udev,pipe, | ||
| 261 | req, | ||
| 262 | request_type, | ||
| 263 | wValue, | ||
| 264 | wIndex, | ||
| 265 | buf, | ||
| 266 | buflen, | ||
| 267 | nWaitTime * HZ); | ||
| 268 | return len == buflen ? 0 : -EREMOTEIO; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* actual bus specific access functions, | ||
| 272 | make sure prototype are/will be equal to pci */ | ||
| 273 | static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, | ||
| 274 | flexcop_ibi_register reg) | ||
| 275 | { | ||
| 276 | flexcop_ibi_value val; | ||
| 277 | val.raw = 0; | ||
| 278 | flexcop_usb_readwrite_dw(fc, reg, &val.raw, 1); | ||
| 279 | return val; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, | ||
| 283 | flexcop_ibi_register reg, flexcop_ibi_value val) | ||
| 284 | { | ||
| 285 | return flexcop_usb_readwrite_dw(fc, reg, &val.raw, 0); | ||
| 286 | } | ||
| 287 | |||
| 288 | static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c, | ||
| 289 | flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) | ||
| 290 | { | ||
| 291 | if (op == FC_READ) | ||
| 292 | return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST, | ||
| 293 | USB_FUNC_I2C_READ, chipaddr, addr, buf, len); | ||
| 294 | else | ||
| 295 | return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST, | ||
| 296 | USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len); | ||
| 297 | } | ||
| 298 | |||
| 299 | static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, | ||
| 300 | u8 *buffer, int buffer_length) | ||
| 301 | { | ||
| 302 | u8 *b; | ||
| 303 | int l; | ||
| 304 | |||
| 305 | deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", | ||
| 306 | fc_usb->tmp_buffer_length, buffer_length); | ||
| 307 | |||
| 308 | if (fc_usb->tmp_buffer_length > 0) { | ||
| 309 | memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, | ||
| 310 | buffer_length); | ||
| 311 | fc_usb->tmp_buffer_length += buffer_length; | ||
| 312 | b = fc_usb->tmp_buffer; | ||
| 313 | l = fc_usb->tmp_buffer_length; | ||
| 314 | } else { | ||
| 315 | b=buffer; | ||
| 316 | l=buffer_length; | ||
| 317 | } | ||
| 318 | |||
| 319 | while (l >= 190) { | ||
| 320 | if (*b == 0xff) { | ||
| 321 | switch (*(b+1) & 0x03) { | ||
| 322 | case 0x01: /* media packet */ | ||
| 323 | if (*(b+2) == 0x47) | ||
| 324 | flexcop_pass_dmx_packets( | ||
| 325 | fc_usb->fc_dev, b+2, 1); | ||
| 326 | else | ||
| 327 | deb_ts( | ||
| 328 | "not ts packet %02x %02x %02x %02x \n", | ||
| 329 | *(b+2), *(b+3), | ||
| 330 | *(b+4), *(b+5)); | ||
| 331 | b += 190; | ||
| 332 | l -= 190; | ||
| 333 | break; | ||
| 334 | default: | ||
| 335 | deb_ts("wrong packet type\n"); | ||
| 336 | l = 0; | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | } else { | ||
| 340 | deb_ts("wrong header\n"); | ||
| 341 | l = 0; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | if (l>0) | ||
| 346 | memcpy(fc_usb->tmp_buffer, b, l); | ||
| 347 | fc_usb->tmp_buffer_length = l; | ||
| 348 | } | ||
| 349 | |||
| 350 | static void flexcop_usb_urb_complete(struct urb *urb) | ||
| 351 | { | ||
| 352 | struct flexcop_usb *fc_usb = urb->context; | ||
| 353 | int i; | ||
| 354 | |||
| 355 | if (urb->actual_length > 0) | ||
| 356 | deb_ts("urb completed, bufsize: %d actlen; %d\n", | ||
| 357 | urb->transfer_buffer_length, urb->actual_length); | ||
| 358 | |||
| 359 | for (i = 0; i < urb->number_of_packets; i++) { | ||
| 360 | if (urb->iso_frame_desc[i].status < 0) { | ||
| 361 | err("iso frame descriptor %d has an error: %d\n", i, | ||
| 362 | urb->iso_frame_desc[i].status); | ||
| 363 | } else | ||
| 364 | if (urb->iso_frame_desc[i].actual_length > 0) { | ||
| 365 | deb_ts("passed %d bytes to the demux\n", | ||
| 366 | urb->iso_frame_desc[i].actual_length); | ||
| 367 | |||
| 368 | flexcop_usb_process_frame(fc_usb, | ||
| 369 | urb->transfer_buffer + | ||
| 370 | urb->iso_frame_desc[i].offset, | ||
| 371 | urb->iso_frame_desc[i].actual_length); | ||
| 372 | } | ||
| 373 | urb->iso_frame_desc[i].status = 0; | ||
| 374 | urb->iso_frame_desc[i].actual_length = 0; | ||
| 375 | } | ||
| 376 | usb_submit_urb(urb,GFP_ATOMIC); | ||
| 377 | } | ||
| 378 | |||
| 379 | static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff) | ||
| 380 | { | ||
| 381 | /* submit/kill iso packets */ | ||
| 382 | return 0; | ||
| 383 | } | ||
| 384 | |||
| 385 | static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb) | ||
| 386 | { | ||
| 387 | int i; | ||
| 388 | for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) | ||
| 389 | if (fc_usb->iso_urb[i] != NULL) { | ||
| 390 | deb_ts("unlinking/killing urb no. %d\n",i); | ||
| 391 | usb_kill_urb(fc_usb->iso_urb[i]); | ||
| 392 | usb_free_urb(fc_usb->iso_urb[i]); | ||
| 393 | } | ||
| 394 | |||
| 395 | if (fc_usb->iso_buffer != NULL) | ||
| 396 | pci_free_consistent(NULL, | ||
| 397 | fc_usb->buffer_size, fc_usb->iso_buffer, | ||
| 398 | fc_usb->dma_addr); | ||
| 399 | } | ||
| 400 | |||
| 401 | static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) | ||
| 402 | { | ||
| 403 | u16 frame_size = le16_to_cpu( | ||
| 404 | fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize); | ||
| 405 | int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * | ||
| 406 | frame_size, i, j, ret; | ||
| 407 | int buffer_offset = 0; | ||
| 408 | |||
| 409 | deb_ts("creating %d iso-urbs with %d frames " | ||
| 410 | "each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB, | ||
| 411 | B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize); | ||
| 412 | |||
| 413 | fc_usb->iso_buffer = pci_alloc_consistent(NULL, | ||
| 414 | bufsize, &fc_usb->dma_addr); | ||
| 415 | if (fc_usb->iso_buffer == NULL) | ||
| 416 | return -ENOMEM; | ||
| 417 | |||
| 418 | memset(fc_usb->iso_buffer, 0, bufsize); | ||
| 419 | fc_usb->buffer_size = bufsize; | ||
| 420 | |||
| 421 | /* creating iso urbs */ | ||
| 422 | for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { | ||
| 423 | fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO, | ||
| 424 | GFP_ATOMIC); | ||
| 425 | if (fc_usb->iso_urb[i] == NULL) { | ||
| 426 | ret = -ENOMEM; | ||
| 427 | goto urb_error; | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | /* initialising and submitting iso urbs */ | ||
| 432 | for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { | ||
| 433 | int frame_offset = 0; | ||
| 434 | struct urb *urb = fc_usb->iso_urb[i]; | ||
| 435 | deb_ts("initializing and submitting urb no. %d " | ||
| 436 | "(buf_offset: %d).\n", i, buffer_offset); | ||
| 437 | |||
| 438 | urb->dev = fc_usb->udev; | ||
| 439 | urb->context = fc_usb; | ||
| 440 | urb->complete = flexcop_usb_urb_complete; | ||
| 441 | urb->pipe = B2C2_USB_DATA_PIPE; | ||
| 442 | urb->transfer_flags = URB_ISO_ASAP; | ||
| 443 | urb->interval = 1; | ||
| 444 | urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO; | ||
| 445 | urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO; | ||
| 446 | urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset; | ||
| 447 | |||
| 448 | buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO; | ||
| 449 | for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) { | ||
| 450 | deb_ts("urb no: %d, frame: %d, frame_offset: %d\n", | ||
| 451 | i, j, frame_offset); | ||
| 452 | urb->iso_frame_desc[j].offset = frame_offset; | ||
| 453 | urb->iso_frame_desc[j].length = frame_size; | ||
| 454 | frame_offset += frame_size; | ||
| 455 | } | ||
| 456 | |||
| 457 | if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) { | ||
| 458 | err("submitting urb %d failed with %d.", i, ret); | ||
| 459 | goto urb_error; | ||
| 460 | } | ||
| 461 | deb_ts("submitted urb no. %d.\n",i); | ||
| 462 | } | ||
| 463 | |||
| 464 | /* SRAM */ | ||
| 465 | flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA | | ||
| 466 | FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, | ||
| 467 | FC_SRAM_DEST_TARGET_WAN_USB); | ||
| 468 | flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS); | ||
| 469 | flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1); | ||
| 470 | return 0; | ||
| 471 | |||
| 472 | urb_error: | ||
| 473 | flexcop_usb_transfer_exit(fc_usb); | ||
| 474 | return ret; | ||
| 475 | } | ||
| 476 | |||
| 477 | static int flexcop_usb_init(struct flexcop_usb *fc_usb) | ||
| 478 | { | ||
| 479 | /* use the alternate setting with the larges buffer */ | ||
| 480 | usb_set_interface(fc_usb->udev,0,1); | ||
| 481 | switch (fc_usb->udev->speed) { | ||
| 482 | case USB_SPEED_LOW: | ||
| 483 | err("cannot handle USB speed because it is too slow."); | ||
| 484 | return -ENODEV; | ||
| 485 | break; | ||
| 486 | case USB_SPEED_FULL: | ||
| 487 | info("running at FULL speed."); | ||
| 488 | break; | ||
| 489 | case USB_SPEED_HIGH: | ||
| 490 | info("running at HIGH speed."); | ||
| 491 | break; | ||
| 492 | case USB_SPEED_UNKNOWN: /* fall through */ | ||
| 493 | default: | ||
| 494 | err("cannot handle USB speed because it is unknown."); | ||
| 495 | return -ENODEV; | ||
| 496 | } | ||
| 497 | usb_set_intfdata(fc_usb->uintf, fc_usb); | ||
| 498 | return 0; | ||
| 499 | } | ||
| 500 | |||
| 501 | static void flexcop_usb_exit(struct flexcop_usb *fc_usb) | ||
| 502 | { | ||
| 503 | usb_set_intfdata(fc_usb->uintf, NULL); | ||
| 504 | } | ||
| 505 | |||
| 506 | static int flexcop_usb_probe(struct usb_interface *intf, | ||
| 507 | const struct usb_device_id *id) | ||
| 508 | { | ||
| 509 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 510 | struct flexcop_usb *fc_usb = NULL; | ||
| 511 | struct flexcop_device *fc = NULL; | ||
| 512 | int ret; | ||
| 513 | |||
| 514 | if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { | ||
| 515 | err("out of memory\n"); | ||
| 516 | return -ENOMEM; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* general flexcop init */ | ||
| 520 | fc_usb = fc->bus_specific; | ||
| 521 | fc_usb->fc_dev = fc; | ||
| 522 | |||
| 523 | fc->read_ibi_reg = flexcop_usb_read_ibi_reg; | ||
| 524 | fc->write_ibi_reg = flexcop_usb_write_ibi_reg; | ||
| 525 | fc->i2c_request = flexcop_usb_i2c_request; | ||
| 526 | fc->get_mac_addr = flexcop_usb_get_mac_addr; | ||
| 527 | |||
| 528 | fc->stream_control = flexcop_usb_stream_control; | ||
| 529 | |||
| 530 | fc->pid_filtering = 1; | ||
| 531 | fc->bus_type = FC_USB; | ||
| 532 | |||
| 533 | fc->dev = &udev->dev; | ||
| 534 | fc->owner = THIS_MODULE; | ||
| 535 | |||
| 536 | /* bus specific part */ | ||
| 537 | fc_usb->udev = udev; | ||
| 538 | fc_usb->uintf = intf; | ||
| 539 | if ((ret = flexcop_usb_init(fc_usb)) != 0) | ||
| 540 | goto err_kfree; | ||
| 541 | |||
| 542 | /* init flexcop */ | ||
| 543 | if ((ret = flexcop_device_initialize(fc)) != 0) | ||
| 544 | goto err_usb_exit; | ||
| 545 | |||
| 546 | /* xfer init */ | ||
| 547 | if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0) | ||
| 548 | goto err_fc_exit; | ||
| 549 | |||
| 550 | info("%s successfully initialized and connected.", DRIVER_NAME); | ||
| 551 | return 0; | ||
| 552 | |||
| 553 | err_fc_exit: | ||
| 554 | flexcop_device_exit(fc); | ||
| 555 | err_usb_exit: | ||
| 556 | flexcop_usb_exit(fc_usb); | ||
| 557 | err_kfree: | ||
| 558 | flexcop_device_kfree(fc); | ||
| 559 | return ret; | ||
| 560 | } | ||
| 561 | |||
| 562 | static void flexcop_usb_disconnect(struct usb_interface *intf) | ||
| 563 | { | ||
| 564 | struct flexcop_usb *fc_usb = usb_get_intfdata(intf); | ||
| 565 | flexcop_usb_transfer_exit(fc_usb); | ||
| 566 | flexcop_device_exit(fc_usb->fc_dev); | ||
| 567 | flexcop_usb_exit(fc_usb); | ||
| 568 | flexcop_device_kfree(fc_usb->fc_dev); | ||
| 569 | info("%s successfully deinitialized and disconnected.", DRIVER_NAME); | ||
| 570 | } | ||
| 571 | |||
| 572 | static struct usb_device_id flexcop_usb_table [] = { | ||
| 573 | { USB_DEVICE(0x0af7, 0x0101) }, | ||
| 574 | { } | ||
| 575 | }; | ||
| 576 | MODULE_DEVICE_TABLE (usb, flexcop_usb_table); | ||
| 577 | |||
| 578 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 579 | static struct usb_driver flexcop_usb_driver = { | ||
| 580 | .name = "b2c2_flexcop_usb", | ||
| 581 | .probe = flexcop_usb_probe, | ||
| 582 | .disconnect = flexcop_usb_disconnect, | ||
| 583 | .id_table = flexcop_usb_table, | ||
| 584 | }; | ||
| 585 | |||
| 586 | /* module stuff */ | ||
| 587 | static int __init flexcop_usb_module_init(void) | ||
| 588 | { | ||
| 589 | int result; | ||
| 590 | if ((result = usb_register(&flexcop_usb_driver))) { | ||
| 591 | err("usb_register failed. (%d)", result); | ||
| 592 | return result; | ||
| 593 | } | ||
| 594 | return 0; | ||
| 595 | } | ||
| 596 | |||
| 597 | static void __exit flexcop_usb_module_exit(void) | ||
| 598 | { | ||
| 599 | /* deregister this driver from the USB subsystem */ | ||
| 600 | usb_deregister(&flexcop_usb_driver); | ||
| 601 | } | ||
| 602 | |||
| 603 | module_init(flexcop_usb_module_init); | ||
| 604 | module_exit(flexcop_usb_module_exit); | ||
| 605 | |||
| 606 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 607 | MODULE_DESCRIPTION(DRIVER_NAME); | ||
| 608 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/dvb/b2c2/flexcop-usb.h new file mode 100644 index 00000000000..92529a9c447 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop-usb.h | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop-usb.h - header file for the USB part | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #ifndef __FLEXCOP_USB_H_INCLUDED__ | ||
| 7 | #define __FLEXCOP_USB_H_INCLUDED__ | ||
| 8 | |||
| 9 | #include <linux/usb.h> | ||
| 10 | |||
| 11 | /* transfer parameters */ | ||
| 12 | #define B2C2_USB_FRAMES_PER_ISO 4 | ||
| 13 | #define B2C2_USB_NUM_ISO_URB 4 | ||
| 14 | |||
| 15 | #define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev, 0) | ||
| 16 | #define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev, 0) | ||
| 17 | #define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev, 0x81) | ||
| 18 | |||
| 19 | struct flexcop_usb { | ||
| 20 | struct usb_device *udev; | ||
| 21 | struct usb_interface *uintf; | ||
| 22 | |||
| 23 | u8 *iso_buffer; | ||
| 24 | int buffer_size; | ||
| 25 | dma_addr_t dma_addr; | ||
| 26 | |||
| 27 | struct urb *iso_urb[B2C2_USB_NUM_ISO_URB]; | ||
| 28 | struct flexcop_device *fc_dev; | ||
| 29 | |||
| 30 | u8 tmp_buffer[1023+190]; | ||
| 31 | int tmp_buffer_length; | ||
| 32 | }; | ||
| 33 | |||
| 34 | #if 0 | ||
| 35 | /* request types TODO What is its use?*/ | ||
| 36 | typedef enum { | ||
| 37 | |||
| 38 | } flexcop_usb_request_type_t; | ||
| 39 | #endif | ||
| 40 | |||
| 41 | /* request */ | ||
| 42 | typedef enum { | ||
| 43 | B2C2_USB_WRITE_V8_MEM = 0x04, | ||
| 44 | B2C2_USB_READ_V8_MEM = 0x05, | ||
| 45 | B2C2_USB_READ_REG = 0x08, | ||
| 46 | B2C2_USB_WRITE_REG = 0x0A, | ||
| 47 | B2C2_USB_WRITEREGHI = 0x0B, | ||
| 48 | B2C2_USB_FLASH_BLOCK = 0x10, | ||
| 49 | B2C2_USB_I2C_REQUEST = 0x11, | ||
| 50 | B2C2_USB_UTILITY = 0x12, | ||
| 51 | } flexcop_usb_request_t; | ||
| 52 | |||
| 53 | /* function definition for I2C_REQUEST */ | ||
| 54 | typedef enum { | ||
| 55 | USB_FUNC_I2C_WRITE = 0x01, | ||
| 56 | USB_FUNC_I2C_MULTIWRITE = 0x02, | ||
| 57 | USB_FUNC_I2C_READ = 0x03, | ||
| 58 | USB_FUNC_I2C_REPEATWRITE = 0x04, | ||
| 59 | USB_FUNC_GET_DESCRIPTOR = 0x05, | ||
| 60 | USB_FUNC_I2C_REPEATREAD = 0x06, | ||
| 61 | /* DKT 020208 - add this to support special case of DiSEqC */ | ||
| 62 | USB_FUNC_I2C_CHECKWRITE = 0x07, | ||
| 63 | USB_FUNC_I2C_CHECKRESULT = 0x08, | ||
| 64 | } flexcop_usb_i2c_function_t; | ||
| 65 | |||
| 66 | /* function definition for UTILITY request 0x12 | ||
| 67 | * DKT 020304 - new utility function */ | ||
| 68 | typedef enum { | ||
| 69 | UTILITY_SET_FILTER = 0x01, | ||
| 70 | UTILITY_DATA_ENABLE = 0x02, | ||
| 71 | UTILITY_FLEX_MULTIWRITE = 0x03, | ||
| 72 | UTILITY_SET_BUFFER_SIZE = 0x04, | ||
| 73 | UTILITY_FLEX_OPERATOR = 0x05, | ||
| 74 | UTILITY_FLEX_RESET300_START = 0x06, | ||
| 75 | UTILITY_FLEX_RESET300_STOP = 0x07, | ||
| 76 | UTILITY_FLEX_RESET300 = 0x08, | ||
| 77 | UTILITY_SET_ISO_SIZE = 0x09, | ||
| 78 | UTILITY_DATA_RESET = 0x0A, | ||
| 79 | UTILITY_GET_DATA_STATUS = 0x10, | ||
| 80 | UTILITY_GET_V8_REG = 0x11, | ||
| 81 | /* DKT 020326 - add function for v1.14 */ | ||
| 82 | UTILITY_SRAM_WRITE = 0x12, | ||
| 83 | UTILITY_SRAM_READ = 0x13, | ||
| 84 | UTILITY_SRAM_TESTFILL = 0x14, | ||
| 85 | UTILITY_SRAM_TESTSET = 0x15, | ||
| 86 | UTILITY_SRAM_TESTVERIFY = 0x16, | ||
| 87 | } flexcop_usb_utility_function_t; | ||
| 88 | |||
| 89 | #define B2C2_WAIT_FOR_OPERATION_RW (1*HZ) | ||
| 90 | #define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ) | ||
| 91 | #define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ) | ||
| 92 | |||
| 93 | #define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ) | ||
| 94 | #define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ) | ||
| 95 | #define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ) | ||
| 96 | |||
| 97 | typedef enum { | ||
| 98 | V8_MEMORY_PAGE_DVB_CI = 0x20, | ||
| 99 | V8_MEMORY_PAGE_DVB_DS = 0x40, | ||
| 100 | V8_MEMORY_PAGE_MULTI2 = 0x60, | ||
| 101 | V8_MEMORY_PAGE_FLASH = 0x80 | ||
| 102 | } flexcop_usb_mem_page_t; | ||
| 103 | |||
| 104 | #define V8_MEMORY_EXTENDED (1 << 15) | ||
| 105 | #define USB_MEM_READ_MAX 32 | ||
| 106 | #define USB_MEM_WRITE_MAX 1 | ||
| 107 | #define USB_FLASH_MAX 8 | ||
| 108 | #define V8_MEMORY_PAGE_SIZE 0x8000 /* 32K */ | ||
| 109 | #define V8_MEMORY_PAGE_MASK 0x7FFF | ||
| 110 | |||
| 111 | #endif | ||
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c new file mode 100644 index 00000000000..2df1b0214dc --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop.c | |||
| @@ -0,0 +1,311 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop.c - main module part | ||
| 4 | * Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de> | ||
| 5 | * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc | ||
| 6 | * | ||
| 7 | * Acknowledgements: | ||
| 8 | * John Jurrius from BBTI, Inc. for extensive support | ||
| 9 | * with code examples and data books | ||
| 10 | * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting) | ||
| 11 | * | ||
| 12 | * Contributions to the skystar2-driver have been done by | ||
| 13 | * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes) | ||
| 14 | * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code) | ||
| 15 | * Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu) | ||
| 16 | * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac | ||
| 17 | * filtering) | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or | ||
| 20 | * modify it under the terms of the GNU Lesser General Public License | ||
| 21 | * as published by the Free Software Foundation; either version 2.1 | ||
| 22 | * of the License, or (at your option) any later version. | ||
| 23 | * | ||
| 24 | * This program is distributed in the hope that it will be useful, | ||
| 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 27 | * GNU General Public License for more details. | ||
| 28 | * | ||
| 29 | * You should have received a copy of the GNU Lesser General Public License | ||
| 30 | * along with this program; if not, write to the Free Software | ||
| 31 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include "flexcop.h" | ||
| 35 | |||
| 36 | #define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip" | ||
| 37 | #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de" | ||
| 38 | |||
| 39 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | ||
| 40 | #define DEBSTATUS "" | ||
| 41 | #else | ||
| 42 | #define DEBSTATUS " (debugging is not enabled)" | ||
| 43 | #endif | ||
| 44 | |||
| 45 | int b2c2_flexcop_debug; | ||
| 46 | module_param_named(debug, b2c2_flexcop_debug, int, 0644); | ||
| 47 | MODULE_PARM_DESC(debug, | ||
| 48 | "set debug level (1=info,2=tuner,4=i2c,8=ts," | ||
| 49 | "16=sram,32=reg (|-able))." | ||
| 50 | DEBSTATUS); | ||
| 51 | #undef DEBSTATUS | ||
| 52 | |||
| 53 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 54 | |||
| 55 | /* global zero for ibi values */ | ||
| 56 | flexcop_ibi_value ibi_zero; | ||
| 57 | |||
| 58 | static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 59 | { | ||
| 60 | struct flexcop_device *fc = dvbdmxfeed->demux->priv; | ||
| 61 | return flexcop_pid_feed_control(fc, dvbdmxfeed, 1); | ||
| 62 | } | ||
| 63 | |||
| 64 | static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 65 | { | ||
| 66 | struct flexcop_device *fc = dvbdmxfeed->demux->priv; | ||
| 67 | return flexcop_pid_feed_control(fc, dvbdmxfeed, 0); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int flexcop_dvb_init(struct flexcop_device *fc) | ||
| 71 | { | ||
| 72 | int ret = dvb_register_adapter(&fc->dvb_adapter, | ||
| 73 | "FlexCop Digital TV device", fc->owner, | ||
| 74 | fc->dev, adapter_nr); | ||
| 75 | if (ret < 0) { | ||
| 76 | err("error registering DVB adapter"); | ||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | fc->dvb_adapter.priv = fc; | ||
| 80 | |||
| 81 | fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | ||
| 82 | | DMX_MEMORY_BASED_FILTERING); | ||
| 83 | fc->demux.priv = fc; | ||
| 84 | fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED; | ||
| 85 | fc->demux.start_feed = flexcop_dvb_start_feed; | ||
| 86 | fc->demux.stop_feed = flexcop_dvb_stop_feed; | ||
| 87 | fc->demux.write_to_decoder = NULL; | ||
| 88 | |||
| 89 | if ((ret = dvb_dmx_init(&fc->demux)) < 0) { | ||
| 90 | err("dvb_dmx failed: error %d", ret); | ||
| 91 | goto err_dmx; | ||
| 92 | } | ||
| 93 | |||
| 94 | fc->hw_frontend.source = DMX_FRONTEND_0; | ||
| 95 | |||
| 96 | fc->dmxdev.filternum = fc->demux.feednum; | ||
| 97 | fc->dmxdev.demux = &fc->demux.dmx; | ||
| 98 | fc->dmxdev.capabilities = 0; | ||
| 99 | if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) { | ||
| 100 | err("dvb_dmxdev_init failed: error %d", ret); | ||
| 101 | goto err_dmx_dev; | ||
| 102 | } | ||
| 103 | |||
| 104 | if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) { | ||
| 105 | err("adding hw_frontend to dmx failed: error %d", ret); | ||
| 106 | goto err_dmx_add_hw_frontend; | ||
| 107 | } | ||
| 108 | |||
| 109 | fc->mem_frontend.source = DMX_MEMORY_FE; | ||
| 110 | if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) { | ||
| 111 | err("adding mem_frontend to dmx failed: error %d", ret); | ||
| 112 | goto err_dmx_add_mem_frontend; | ||
| 113 | } | ||
| 114 | |||
| 115 | if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) { | ||
| 116 | err("connect frontend failed: error %d", ret); | ||
| 117 | goto err_connect_frontend; | ||
| 118 | } | ||
| 119 | |||
| 120 | dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx); | ||
| 121 | |||
| 122 | fc->init_state |= FC_STATE_DVB_INIT; | ||
| 123 | return 0; | ||
| 124 | |||
| 125 | err_connect_frontend: | ||
| 126 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend); | ||
| 127 | err_dmx_add_mem_frontend: | ||
| 128 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->hw_frontend); | ||
| 129 | err_dmx_add_hw_frontend: | ||
| 130 | dvb_dmxdev_release(&fc->dmxdev); | ||
| 131 | err_dmx_dev: | ||
| 132 | dvb_dmx_release(&fc->demux); | ||
| 133 | err_dmx: | ||
| 134 | dvb_unregister_adapter(&fc->dvb_adapter); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 138 | static void flexcop_dvb_exit(struct flexcop_device *fc) | ||
| 139 | { | ||
| 140 | if (fc->init_state & FC_STATE_DVB_INIT) { | ||
| 141 | dvb_net_release(&fc->dvbnet); | ||
| 142 | |||
| 143 | fc->demux.dmx.close(&fc->demux.dmx); | ||
| 144 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, | ||
| 145 | &fc->mem_frontend); | ||
| 146 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, | ||
| 147 | &fc->hw_frontend); | ||
| 148 | dvb_dmxdev_release(&fc->dmxdev); | ||
| 149 | dvb_dmx_release(&fc->demux); | ||
| 150 | dvb_unregister_adapter(&fc->dvb_adapter); | ||
| 151 | deb_info("deinitialized dvb stuff\n"); | ||
| 152 | } | ||
| 153 | fc->init_state &= ~FC_STATE_DVB_INIT; | ||
| 154 | } | ||
| 155 | |||
| 156 | /* these methods are necessary to achieve the long-term-goal of hiding the | ||
| 157 | * struct flexcop_device from the bus-parts */ | ||
| 158 | void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len) | ||
| 159 | { | ||
| 160 | dvb_dmx_swfilter(&fc->demux, buf, len); | ||
| 161 | } | ||
| 162 | EXPORT_SYMBOL(flexcop_pass_dmx_data); | ||
| 163 | |||
| 164 | void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no) | ||
| 165 | { | ||
| 166 | dvb_dmx_swfilter_packets(&fc->demux, buf, no); | ||
| 167 | } | ||
| 168 | EXPORT_SYMBOL(flexcop_pass_dmx_packets); | ||
| 169 | |||
| 170 | static void flexcop_reset(struct flexcop_device *fc) | ||
| 171 | { | ||
| 172 | flexcop_ibi_value v210, v204; | ||
| 173 | |||
| 174 | /* reset the flexcop itself */ | ||
| 175 | fc->write_ibi_reg(fc,ctrl_208,ibi_zero); | ||
| 176 | |||
| 177 | v210.raw = 0; | ||
| 178 | v210.sw_reset_210.reset_block_000 = 1; | ||
| 179 | v210.sw_reset_210.reset_block_100 = 1; | ||
| 180 | v210.sw_reset_210.reset_block_200 = 1; | ||
| 181 | v210.sw_reset_210.reset_block_300 = 1; | ||
| 182 | v210.sw_reset_210.reset_block_400 = 1; | ||
| 183 | v210.sw_reset_210.reset_block_500 = 1; | ||
| 184 | v210.sw_reset_210.reset_block_600 = 1; | ||
| 185 | v210.sw_reset_210.reset_block_700 = 1; | ||
| 186 | v210.sw_reset_210.Block_reset_enable = 0xb2; | ||
| 187 | v210.sw_reset_210.Special_controls = 0xc259; | ||
| 188 | fc->write_ibi_reg(fc,sw_reset_210,v210); | ||
| 189 | msleep(1); | ||
| 190 | |||
| 191 | /* reset the periphical devices */ | ||
| 192 | |||
| 193 | v204 = fc->read_ibi_reg(fc,misc_204); | ||
| 194 | v204.misc_204.Per_reset_sig = 0; | ||
| 195 | fc->write_ibi_reg(fc,misc_204,v204); | ||
| 196 | msleep(1); | ||
| 197 | v204.misc_204.Per_reset_sig = 1; | ||
| 198 | fc->write_ibi_reg(fc,misc_204,v204); | ||
| 199 | } | ||
| 200 | |||
| 201 | void flexcop_reset_block_300(struct flexcop_device *fc) | ||
| 202 | { | ||
| 203 | flexcop_ibi_value v208_save = fc->read_ibi_reg(fc, ctrl_208), | ||
| 204 | v210 = fc->read_ibi_reg(fc, sw_reset_210); | ||
| 205 | |||
| 206 | deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw); | ||
| 207 | fc->write_ibi_reg(fc,ctrl_208,ibi_zero); | ||
| 208 | |||
| 209 | v210.sw_reset_210.reset_block_300 = 1; | ||
| 210 | v210.sw_reset_210.Block_reset_enable = 0xb2; | ||
| 211 | |||
| 212 | fc->write_ibi_reg(fc,sw_reset_210,v210); | ||
| 213 | fc->write_ibi_reg(fc,ctrl_208,v208_save); | ||
| 214 | } | ||
| 215 | |||
| 216 | struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) | ||
| 217 | { | ||
| 218 | void *bus; | ||
| 219 | struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), | ||
| 220 | GFP_KERNEL); | ||
| 221 | if (!fc) { | ||
| 222 | err("no memory"); | ||
| 223 | return NULL; | ||
| 224 | } | ||
| 225 | |||
| 226 | bus = kzalloc(bus_specific_len, GFP_KERNEL); | ||
| 227 | if (!bus) { | ||
| 228 | err("no memory"); | ||
| 229 | kfree(fc); | ||
| 230 | return NULL; | ||
| 231 | } | ||
| 232 | |||
| 233 | fc->bus_specific = bus; | ||
| 234 | |||
| 235 | return fc; | ||
| 236 | } | ||
| 237 | EXPORT_SYMBOL(flexcop_device_kmalloc); | ||
| 238 | |||
| 239 | void flexcop_device_kfree(struct flexcop_device *fc) | ||
| 240 | { | ||
| 241 | kfree(fc->bus_specific); | ||
| 242 | kfree(fc); | ||
| 243 | } | ||
| 244 | EXPORT_SYMBOL(flexcop_device_kfree); | ||
| 245 | |||
| 246 | int flexcop_device_initialize(struct flexcop_device *fc) | ||
| 247 | { | ||
| 248 | int ret; | ||
| 249 | ibi_zero.raw = 0; | ||
| 250 | |||
| 251 | flexcop_reset(fc); | ||
| 252 | flexcop_determine_revision(fc); | ||
| 253 | flexcop_sram_init(fc); | ||
| 254 | flexcop_hw_filter_init(fc); | ||
| 255 | flexcop_smc_ctrl(fc, 0); | ||
| 256 | |||
| 257 | if ((ret = flexcop_dvb_init(fc))) | ||
| 258 | goto error; | ||
| 259 | |||
| 260 | /* i2c has to be done before doing EEProm stuff - | ||
| 261 | * because the EEProm is accessed via i2c */ | ||
| 262 | ret = flexcop_i2c_init(fc); | ||
| 263 | if (ret) | ||
| 264 | goto error; | ||
| 265 | |||
| 266 | /* do the MAC address reading after initializing the dvb_adapter */ | ||
| 267 | if (fc->get_mac_addr(fc, 0) == 0) { | ||
| 268 | u8 *b = fc->dvb_adapter.proposed_mac; | ||
| 269 | info("MAC address = %pM", b); | ||
| 270 | flexcop_set_mac_filter(fc,b); | ||
| 271 | flexcop_mac_filter_ctrl(fc,1); | ||
| 272 | } else | ||
| 273 | warn("reading of MAC address failed.\n"); | ||
| 274 | |||
| 275 | if ((ret = flexcop_frontend_init(fc))) | ||
| 276 | goto error; | ||
| 277 | |||
| 278 | flexcop_device_name(fc,"initialization of","complete"); | ||
| 279 | return 0; | ||
| 280 | |||
| 281 | error: | ||
| 282 | flexcop_device_exit(fc); | ||
| 283 | return ret; | ||
| 284 | } | ||
| 285 | EXPORT_SYMBOL(flexcop_device_initialize); | ||
| 286 | |||
| 287 | void flexcop_device_exit(struct flexcop_device *fc) | ||
| 288 | { | ||
| 289 | flexcop_frontend_exit(fc); | ||
| 290 | flexcop_i2c_exit(fc); | ||
| 291 | flexcop_dvb_exit(fc); | ||
| 292 | } | ||
| 293 | EXPORT_SYMBOL(flexcop_device_exit); | ||
| 294 | |||
| 295 | static int flexcop_module_init(void) | ||
| 296 | { | ||
| 297 | info(DRIVER_NAME " loaded successfully"); | ||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static void flexcop_module_cleanup(void) | ||
| 302 | { | ||
| 303 | info(DRIVER_NAME " unloaded successfully"); | ||
| 304 | } | ||
| 305 | |||
| 306 | module_init(flexcop_module_init); | ||
| 307 | module_exit(flexcop_module_cleanup); | ||
| 308 | |||
| 309 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 310 | MODULE_DESCRIPTION(DRIVER_NAME); | ||
| 311 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/dvb/b2c2/flexcop.h new file mode 100644 index 00000000000..897b10c85ad --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 3 | * flexcop.h - private header file for all flexcop-chip-source files | ||
| 4 | * see flexcop.c for copyright information | ||
| 5 | */ | ||
| 6 | #ifndef __FLEXCOP_H__ | ||
| 7 | #define __FLEXCOP_H___ | ||
| 8 | |||
| 9 | #define FC_LOG_PREFIX "b2c2-flexcop" | ||
| 10 | #include "flexcop-common.h" | ||
| 11 | |||
| 12 | extern int b2c2_flexcop_debug; | ||
| 13 | |||
| 14 | /* debug */ | ||
| 15 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | ||
| 16 | #define dprintk(level,args...) \ | ||
| 17 | do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0) | ||
| 18 | #else | ||
| 19 | #define dprintk(level,args...) | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #define deb_info(args...) dprintk(0x01, args) | ||
| 23 | #define deb_tuner(args...) dprintk(0x02, args) | ||
| 24 | #define deb_i2c(args...) dprintk(0x04, args) | ||
| 25 | #define deb_ts(args...) dprintk(0x08, args) | ||
| 26 | #define deb_sram(args...) dprintk(0x10, args) | ||
| 27 | #define deb_rdump(args...) dprintk(0x20, args) | ||
| 28 | |||
| 29 | #endif | ||
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h new file mode 100644 index 00000000000..8f64bdbd72b --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h | |||
| @@ -0,0 +1,455 @@ | |||
| 1 | /* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 2 | * register descriptions | ||
| 3 | * see flexcop.c for copyright information | ||
| 4 | */ | ||
| 5 | /* This file is automatically generated, do not edit things here. */ | ||
| 6 | #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
| 7 | #define __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
| 8 | |||
| 9 | typedef union { | ||
| 10 | u32 raw; | ||
| 11 | |||
| 12 | struct { | ||
| 13 | u32 dma_address0 :30; | ||
| 14 | u32 dma_0No_update : 1; | ||
| 15 | u32 dma_0start : 1; | ||
| 16 | } dma_0x0; | ||
| 17 | |||
| 18 | struct { | ||
| 19 | u32 dma_addr_size :24; | ||
| 20 | u32 DMA_maxpackets : 8; | ||
| 21 | } dma_0x4_remap; | ||
| 22 | |||
| 23 | struct { | ||
| 24 | u32 dma_addr_size :24; | ||
| 25 | u32 unused : 1; | ||
| 26 | u32 dma1timer : 7; | ||
| 27 | } dma_0x4_read; | ||
| 28 | |||
| 29 | struct { | ||
| 30 | u32 dma_addr_size :24; | ||
| 31 | u32 dmatimer : 7; | ||
| 32 | u32 unused : 1; | ||
| 33 | } dma_0x4_write; | ||
| 34 | |||
| 35 | struct { | ||
| 36 | u32 dma_cur_addr :30; | ||
| 37 | u32 unused : 2; | ||
| 38 | } dma_0x8; | ||
| 39 | |||
| 40 | struct { | ||
| 41 | u32 dma_address1 :30; | ||
| 42 | u32 remap_enable : 1; | ||
| 43 | u32 dma_1start : 1; | ||
| 44 | } dma_0xc; | ||
| 45 | |||
| 46 | struct { | ||
| 47 | u32 st_done : 1; | ||
| 48 | u32 no_base_addr_ack_error : 1; | ||
| 49 | u32 twoWS_port_reg : 2; | ||
| 50 | u32 total_bytes : 2; | ||
| 51 | u32 twoWS_rw : 1; | ||
| 52 | u32 working_start : 1; | ||
| 53 | u32 data1_reg : 8; | ||
| 54 | u32 baseaddr : 8; | ||
| 55 | u32 reserved1 : 1; | ||
| 56 | u32 chipaddr : 7; | ||
| 57 | } tw_sm_c_100; | ||
| 58 | |||
| 59 | struct { | ||
| 60 | u32 unused : 6; | ||
| 61 | u32 force_stop : 1; | ||
| 62 | u32 exlicit_stops : 1; | ||
| 63 | u32 data4_reg : 8; | ||
| 64 | u32 data3_reg : 8; | ||
| 65 | u32 data2_reg : 8; | ||
| 66 | } tw_sm_c_104; | ||
| 67 | |||
| 68 | struct { | ||
| 69 | u32 reserved2 :19; | ||
| 70 | u32 tlo1 : 5; | ||
| 71 | u32 reserved1 : 2; | ||
| 72 | u32 thi1 : 6; | ||
| 73 | } tw_sm_c_108; | ||
| 74 | |||
| 75 | struct { | ||
| 76 | u32 reserved2 :19; | ||
| 77 | u32 tlo1 : 5; | ||
| 78 | u32 reserved1 : 2; | ||
| 79 | u32 thi1 : 6; | ||
| 80 | } tw_sm_c_10c; | ||
| 81 | |||
| 82 | struct { | ||
| 83 | u32 reserved2 :19; | ||
| 84 | u32 tlo1 : 5; | ||
| 85 | u32 reserved1 : 2; | ||
| 86 | u32 thi1 : 6; | ||
| 87 | } tw_sm_c_110; | ||
| 88 | |||
| 89 | struct { | ||
| 90 | u32 LNB_CTLPrescaler_sig : 2; | ||
| 91 | u32 LNB_CTLLowCount_sig :15; | ||
| 92 | u32 LNB_CTLHighCount_sig :15; | ||
| 93 | } lnb_switch_freq_200; | ||
| 94 | |||
| 95 | struct { | ||
| 96 | u32 Rev_N_sig_reserved2 : 1; | ||
| 97 | u32 Rev_N_sig_caps : 1; | ||
| 98 | u32 Rev_N_sig_reserved1 : 2; | ||
| 99 | u32 Rev_N_sig_revision_hi : 4; | ||
| 100 | u32 reserved :20; | ||
| 101 | u32 Per_reset_sig : 1; | ||
| 102 | u32 LNB_L_H_sig : 1; | ||
| 103 | u32 ACPI3_sig : 1; | ||
| 104 | u32 ACPI1_sig : 1; | ||
| 105 | } misc_204; | ||
| 106 | |||
| 107 | struct { | ||
| 108 | u32 unused : 9; | ||
| 109 | u32 Mailbox_from_V8_Enable_sig : 1; | ||
| 110 | u32 DMA2_Size_IRQ_Enable_sig : 1; | ||
| 111 | u32 DMA1_Size_IRQ_Enable_sig : 1; | ||
| 112 | u32 DMA2_Timer_Enable_sig : 1; | ||
| 113 | u32 DMA2_IRQ_Enable_sig : 1; | ||
| 114 | u32 DMA1_Timer_Enable_sig : 1; | ||
| 115 | u32 DMA1_IRQ_Enable_sig : 1; | ||
| 116 | u32 Rcv_Data_sig : 1; | ||
| 117 | u32 MAC_filter_Mode_sig : 1; | ||
| 118 | u32 Multi2_Enable_sig : 1; | ||
| 119 | u32 Per_CA_Enable_sig : 1; | ||
| 120 | u32 SMC_Enable_sig : 1; | ||
| 121 | u32 CA_Enable_sig : 1; | ||
| 122 | u32 WAN_CA_Enable_sig : 1; | ||
| 123 | u32 WAN_Enable_sig : 1; | ||
| 124 | u32 Mask_filter_sig : 1; | ||
| 125 | u32 Null_filter_sig : 1; | ||
| 126 | u32 ECM_filter_sig : 1; | ||
| 127 | u32 EMM_filter_sig : 1; | ||
| 128 | u32 PMT_filter_sig : 1; | ||
| 129 | u32 PCR_filter_sig : 1; | ||
| 130 | u32 Stream2_filter_sig : 1; | ||
| 131 | u32 Stream1_filter_sig : 1; | ||
| 132 | } ctrl_208; | ||
| 133 | |||
| 134 | struct { | ||
| 135 | u32 reserved :21; | ||
| 136 | u32 Transport_Error : 1; | ||
| 137 | u32 LLC_SNAP_FLAG_set : 1; | ||
| 138 | u32 Continuity_error_flag : 1; | ||
| 139 | u32 Data_receiver_error : 1; | ||
| 140 | u32 Mailbox_from_V8_Status_sig : 1; | ||
| 141 | u32 DMA2_Size_IRQ_Status : 1; | ||
| 142 | u32 DMA1_Size_IRQ_Status : 1; | ||
| 143 | u32 DMA2_Timer_Status : 1; | ||
| 144 | u32 DMA2_IRQ_Status : 1; | ||
| 145 | u32 DMA1_Timer_Status : 1; | ||
| 146 | u32 DMA1_IRQ_Status : 1; | ||
| 147 | } irq_20c; | ||
| 148 | |||
| 149 | struct { | ||
| 150 | u32 Special_controls :16; | ||
| 151 | u32 Block_reset_enable : 8; | ||
| 152 | u32 reset_block_700 : 1; | ||
| 153 | u32 reset_block_600 : 1; | ||
| 154 | u32 reset_block_500 : 1; | ||
| 155 | u32 reset_block_400 : 1; | ||
| 156 | u32 reset_block_300 : 1; | ||
| 157 | u32 reset_block_200 : 1; | ||
| 158 | u32 reset_block_100 : 1; | ||
| 159 | u32 reset_block_000 : 1; | ||
| 160 | } sw_reset_210; | ||
| 161 | |||
| 162 | struct { | ||
| 163 | u32 unused2 :20; | ||
| 164 | u32 polarity_PS_ERR_sig : 1; | ||
| 165 | u32 polarity_PS_SYNC_sig : 1; | ||
| 166 | u32 polarity_PS_VALID_sig : 1; | ||
| 167 | u32 polarity_PS_CLK_sig : 1; | ||
| 168 | u32 unused1 : 3; | ||
| 169 | u32 s2p_sel_sig : 1; | ||
| 170 | u32 section_pkg_enable_sig : 1; | ||
| 171 | u32 halt_V8_sig : 1; | ||
| 172 | u32 v2WS_oe_sig : 1; | ||
| 173 | u32 vuart_oe_sig : 1; | ||
| 174 | } misc_214; | ||
| 175 | |||
| 176 | struct { | ||
| 177 | u32 Mailbox_from_V8 :32; | ||
| 178 | } mbox_v8_to_host_218; | ||
| 179 | |||
| 180 | struct { | ||
| 181 | u32 sysramaccess_busmuster : 1; | ||
| 182 | u32 sysramaccess_write : 1; | ||
| 183 | u32 unused : 7; | ||
| 184 | u32 sysramaccess_addr :15; | ||
| 185 | u32 sysramaccess_data : 8; | ||
| 186 | } mbox_host_to_v8_21c; | ||
| 187 | |||
| 188 | struct { | ||
| 189 | u32 debug_fifo_problem : 1; | ||
| 190 | u32 debug_flag_write_status00 : 1; | ||
| 191 | u32 Stream2_trans : 1; | ||
| 192 | u32 Stream2_PID :13; | ||
| 193 | u32 debug_flag_pid_saved : 1; | ||
| 194 | u32 MAC_Multicast_filter : 1; | ||
| 195 | u32 Stream1_trans : 1; | ||
| 196 | u32 Stream1_PID :13; | ||
| 197 | } pid_filter_300; | ||
| 198 | |||
| 199 | struct { | ||
| 200 | u32 reserved : 2; | ||
| 201 | u32 PMT_trans : 1; | ||
| 202 | u32 PMT_PID :13; | ||
| 203 | u32 debug_overrun2 : 1; | ||
| 204 | u32 debug_overrun3 : 1; | ||
| 205 | u32 PCR_trans : 1; | ||
| 206 | u32 PCR_PID :13; | ||
| 207 | } pid_filter_304; | ||
| 208 | |||
| 209 | struct { | ||
| 210 | u32 reserved : 2; | ||
| 211 | u32 ECM_trans : 1; | ||
| 212 | u32 ECM_PID :13; | ||
| 213 | u32 EMM_filter_6 : 1; | ||
| 214 | u32 EMM_filter_4 : 1; | ||
| 215 | u32 EMM_trans : 1; | ||
| 216 | u32 EMM_PID :13; | ||
| 217 | } pid_filter_308; | ||
| 218 | |||
| 219 | struct { | ||
| 220 | u32 unused2 : 3; | ||
| 221 | u32 Group_mask :13; | ||
| 222 | u32 unused1 : 2; | ||
| 223 | u32 Group_trans : 1; | ||
| 224 | u32 Group_PID :13; | ||
| 225 | } pid_filter_30c_ext_ind_0_7; | ||
| 226 | |||
| 227 | struct { | ||
| 228 | u32 unused :15; | ||
| 229 | u32 net_master_read :17; | ||
| 230 | } pid_filter_30c_ext_ind_1; | ||
| 231 | |||
| 232 | struct { | ||
| 233 | u32 unused :15; | ||
| 234 | u32 net_master_write :17; | ||
| 235 | } pid_filter_30c_ext_ind_2; | ||
| 236 | |||
| 237 | struct { | ||
| 238 | u32 unused :15; | ||
| 239 | u32 next_net_master_write :17; | ||
| 240 | } pid_filter_30c_ext_ind_3; | ||
| 241 | |||
| 242 | struct { | ||
| 243 | u32 reserved2 : 5; | ||
| 244 | u32 stack_read :10; | ||
| 245 | u32 reserved1 : 6; | ||
| 246 | u32 state_write :10; | ||
| 247 | u32 unused1 : 1; | ||
| 248 | } pid_filter_30c_ext_ind_4; | ||
| 249 | |||
| 250 | struct { | ||
| 251 | u32 unused :22; | ||
| 252 | u32 stack_cnt :10; | ||
| 253 | } pid_filter_30c_ext_ind_5; | ||
| 254 | |||
| 255 | struct { | ||
| 256 | u32 unused : 4; | ||
| 257 | u32 data_size_reg :12; | ||
| 258 | u32 write_status4 : 2; | ||
| 259 | u32 write_status1 : 2; | ||
| 260 | u32 pid_fsm_save_reg300 : 2; | ||
| 261 | u32 pid_fsm_save_reg4 : 2; | ||
| 262 | u32 pid_fsm_save_reg3 : 2; | ||
| 263 | u32 pid_fsm_save_reg2 : 2; | ||
| 264 | u32 pid_fsm_save_reg1 : 2; | ||
| 265 | u32 pid_fsm_save_reg0 : 2; | ||
| 266 | } pid_filter_30c_ext_ind_6; | ||
| 267 | |||
| 268 | struct { | ||
| 269 | u32 unused :22; | ||
| 270 | u32 pass_alltables : 1; | ||
| 271 | u32 AB_select : 1; | ||
| 272 | u32 extra_index_reg : 3; | ||
| 273 | u32 index_reg : 5; | ||
| 274 | } index_reg_310; | ||
| 275 | |||
| 276 | struct { | ||
| 277 | u32 reserved :17; | ||
| 278 | u32 PID_enable_bit : 1; | ||
| 279 | u32 PID_trans : 1; | ||
| 280 | u32 PID :13; | ||
| 281 | } pid_n_reg_314; | ||
| 282 | |||
| 283 | struct { | ||
| 284 | u32 reserved : 6; | ||
| 285 | u32 HighAB_bit : 1; | ||
| 286 | u32 Enable_bit : 1; | ||
| 287 | u32 A6_byte : 8; | ||
| 288 | u32 A5_byte : 8; | ||
| 289 | u32 A4_byte : 8; | ||
| 290 | } mac_low_reg_318; | ||
| 291 | |||
| 292 | struct { | ||
| 293 | u32 reserved : 8; | ||
| 294 | u32 A3_byte : 8; | ||
| 295 | u32 A2_byte : 8; | ||
| 296 | u32 A1_byte : 8; | ||
| 297 | } mac_high_reg_31c; | ||
| 298 | |||
| 299 | struct { | ||
| 300 | u32 data_Tag_ID :16; | ||
| 301 | u32 reserved :16; | ||
| 302 | } data_tag_400; | ||
| 303 | |||
| 304 | struct { | ||
| 305 | u32 Card_IDbyte3 : 8; | ||
| 306 | u32 Card_IDbyte4 : 8; | ||
| 307 | u32 Card_IDbyte5 : 8; | ||
| 308 | u32 Card_IDbyte6 : 8; | ||
| 309 | } card_id_408; | ||
| 310 | |||
| 311 | struct { | ||
| 312 | u32 Card_IDbyte1 : 8; | ||
| 313 | u32 Card_IDbyte2 : 8; | ||
| 314 | } card_id_40c; | ||
| 315 | |||
| 316 | struct { | ||
| 317 | u32 MAC6 : 8; | ||
| 318 | u32 MAC3 : 8; | ||
| 319 | u32 MAC2 : 8; | ||
| 320 | u32 MAC1 : 8; | ||
| 321 | } mac_address_418; | ||
| 322 | |||
| 323 | struct { | ||
| 324 | u32 reserved :16; | ||
| 325 | u32 MAC8 : 8; | ||
| 326 | u32 MAC7 : 8; | ||
| 327 | } mac_address_41c; | ||
| 328 | |||
| 329 | struct { | ||
| 330 | u32 reserved :21; | ||
| 331 | u32 txbuffempty : 1; | ||
| 332 | u32 ReceiveByteFrameError : 1; | ||
| 333 | u32 ReceiveDataReady : 1; | ||
| 334 | u32 transmitter_data_byte : 8; | ||
| 335 | } ci_600; | ||
| 336 | |||
| 337 | struct { | ||
| 338 | u32 pi_component_reg : 3; | ||
| 339 | u32 pi_rw : 1; | ||
| 340 | u32 pi_ha :20; | ||
| 341 | u32 pi_d : 8; | ||
| 342 | } pi_604; | ||
| 343 | |||
| 344 | struct { | ||
| 345 | u32 pi_busy_n : 1; | ||
| 346 | u32 pi_wait_n : 1; | ||
| 347 | u32 pi_timeout_status : 1; | ||
| 348 | u32 pi_CiMax_IRQ_n : 1; | ||
| 349 | u32 config_cclk : 1; | ||
| 350 | u32 config_cs_n : 1; | ||
| 351 | u32 config_wr_n : 1; | ||
| 352 | u32 config_Prog_n : 1; | ||
| 353 | u32 config_Init_stat : 1; | ||
| 354 | u32 config_Done_stat : 1; | ||
| 355 | u32 pcmcia_b_mod_pwr_n : 1; | ||
| 356 | u32 pcmcia_a_mod_pwr_n : 1; | ||
| 357 | u32 reserved : 3; | ||
| 358 | u32 Timer_addr : 5; | ||
| 359 | u32 unused : 1; | ||
| 360 | u32 timer_data : 7; | ||
| 361 | u32 Timer_Load_req : 1; | ||
| 362 | u32 Timer_Read_req : 1; | ||
| 363 | u32 oncecycle_read : 1; | ||
| 364 | u32 serialReset : 1; | ||
| 365 | } pi_608; | ||
| 366 | |||
| 367 | struct { | ||
| 368 | u32 reserved : 6; | ||
| 369 | u32 rw_flag : 1; | ||
| 370 | u32 dvb_en : 1; | ||
| 371 | u32 key_array_row : 5; | ||
| 372 | u32 key_array_col : 3; | ||
| 373 | u32 key_code : 2; | ||
| 374 | u32 key_enable : 1; | ||
| 375 | u32 PID :13; | ||
| 376 | } dvb_reg_60c; | ||
| 377 | |||
| 378 | struct { | ||
| 379 | u32 start_sram_ibi : 1; | ||
| 380 | u32 reserved2 : 1; | ||
| 381 | u32 ce_pin_reg : 1; | ||
| 382 | u32 oe_pin_reg : 1; | ||
| 383 | u32 reserved1 : 3; | ||
| 384 | u32 sc_xfer_bit : 1; | ||
| 385 | u32 sram_data : 8; | ||
| 386 | u32 sram_rw : 1; | ||
| 387 | u32 sram_addr :15; | ||
| 388 | } sram_ctrl_reg_700; | ||
| 389 | |||
| 390 | struct { | ||
| 391 | u32 net_addr_write :16; | ||
| 392 | u32 net_addr_read :16; | ||
| 393 | } net_buf_reg_704; | ||
| 394 | |||
| 395 | struct { | ||
| 396 | u32 cai_cnt : 4; | ||
| 397 | u32 reserved2 : 6; | ||
| 398 | u32 cai_write :11; | ||
| 399 | u32 reserved1 : 5; | ||
| 400 | u32 cai_read :11; | ||
| 401 | } cai_buf_reg_708; | ||
| 402 | |||
| 403 | struct { | ||
| 404 | u32 cao_cnt : 4; | ||
| 405 | u32 reserved2 : 6; | ||
| 406 | u32 cap_write :11; | ||
| 407 | u32 reserved1 : 5; | ||
| 408 | u32 cao_read :11; | ||
| 409 | } cao_buf_reg_70c; | ||
| 410 | |||
| 411 | struct { | ||
| 412 | u32 media_cnt : 4; | ||
| 413 | u32 reserved2 : 6; | ||
| 414 | u32 media_write :11; | ||
| 415 | u32 reserved1 : 5; | ||
| 416 | u32 media_read :11; | ||
| 417 | } media_buf_reg_710; | ||
| 418 | |||
| 419 | struct { | ||
| 420 | u32 reserved :17; | ||
| 421 | u32 ctrl_maximumfill : 1; | ||
| 422 | u32 ctrl_sramdma : 1; | ||
| 423 | u32 ctrl_usb_wan : 1; | ||
| 424 | u32 cao_ovflow_error : 1; | ||
| 425 | u32 cai_ovflow_error : 1; | ||
| 426 | u32 media_ovflow_error : 1; | ||
| 427 | u32 net_ovflow_error : 1; | ||
| 428 | u32 MEDIA_Dest : 2; | ||
| 429 | u32 CAO_Dest : 2; | ||
| 430 | u32 CAI_Dest : 2; | ||
| 431 | u32 NET_Dest : 2; | ||
| 432 | } sram_dest_reg_714; | ||
| 433 | |||
| 434 | struct { | ||
| 435 | u32 reserved3 :11; | ||
| 436 | u32 net_addr_write : 1; | ||
| 437 | u32 reserved2 : 3; | ||
| 438 | u32 net_addr_read : 1; | ||
| 439 | u32 reserved1 : 4; | ||
| 440 | u32 net_cnt :12; | ||
| 441 | } net_buf_reg_718; | ||
| 442 | |||
| 443 | struct { | ||
| 444 | u32 reserved3 : 4; | ||
| 445 | u32 wan_pkt_frame : 4; | ||
| 446 | u32 reserved2 : 4; | ||
| 447 | u32 sram_memmap : 2; | ||
| 448 | u32 sram_chip : 2; | ||
| 449 | u32 wan_wait_state : 8; | ||
| 450 | u32 reserved1 : 6; | ||
| 451 | u32 wan_speed_sig : 2; | ||
| 452 | } wan_ctrl_reg_71c; | ||
| 453 | } flexcop_ibi_value; | ||
| 454 | |||
| 455 | #endif | ||
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h new file mode 100644 index 00000000000..c75830d7d94 --- /dev/null +++ b/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h | |||
| @@ -0,0 +1,455 @@ | |||
| 1 | /* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
| 2 | * register descriptions | ||
| 3 | * see flexcop.c for copyright information | ||
| 4 | */ | ||
| 5 | /* This file is automatically generated, do not edit things here. */ | ||
| 6 | #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
| 7 | #define __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
| 8 | |||
| 9 | typedef union { | ||
| 10 | u32 raw; | ||
| 11 | |||
| 12 | struct { | ||
| 13 | u32 dma_0start : 1; | ||
| 14 | u32 dma_0No_update : 1; | ||
| 15 | u32 dma_address0 :30; | ||
| 16 | } dma_0x0; | ||
| 17 | |||
| 18 | struct { | ||
| 19 | u32 DMA_maxpackets : 8; | ||
| 20 | u32 dma_addr_size :24; | ||
| 21 | } dma_0x4_remap; | ||
| 22 | |||
| 23 | struct { | ||
| 24 | u32 dma1timer : 7; | ||
| 25 | u32 unused : 1; | ||
| 26 | u32 dma_addr_size :24; | ||
| 27 | } dma_0x4_read; | ||
| 28 | |||
| 29 | struct { | ||
| 30 | u32 unused : 1; | ||
| 31 | u32 dmatimer : 7; | ||
| 32 | u32 dma_addr_size :24; | ||
| 33 | } dma_0x4_write; | ||
| 34 | |||
| 35 | struct { | ||
| 36 | u32 unused : 2; | ||
| 37 | u32 dma_cur_addr :30; | ||
| 38 | } dma_0x8; | ||
| 39 | |||
| 40 | struct { | ||
| 41 | u32 dma_1start : 1; | ||
| 42 | u32 remap_enable : 1; | ||
| 43 | u32 dma_address1 :30; | ||
| 44 | } dma_0xc; | ||
| 45 | |||
| 46 | struct { | ||
| 47 | u32 chipaddr : 7; | ||
| 48 | u32 reserved1 : 1; | ||
| 49 | u32 baseaddr : 8; | ||
| 50 | u32 data1_reg : 8; | ||
| 51 | u32 working_start : 1; | ||
| 52 | u32 twoWS_rw : 1; | ||
| 53 | u32 total_bytes : 2; | ||
| 54 | u32 twoWS_port_reg : 2; | ||
| 55 | u32 no_base_addr_ack_error : 1; | ||
| 56 | u32 st_done : 1; | ||
| 57 | } tw_sm_c_100; | ||
| 58 | |||
| 59 | struct { | ||
| 60 | u32 data2_reg : 8; | ||
| 61 | u32 data3_reg : 8; | ||
| 62 | u32 data4_reg : 8; | ||
| 63 | u32 exlicit_stops : 1; | ||
| 64 | u32 force_stop : 1; | ||
| 65 | u32 unused : 6; | ||
| 66 | } tw_sm_c_104; | ||
| 67 | |||
| 68 | struct { | ||
| 69 | u32 thi1 : 6; | ||
| 70 | u32 reserved1 : 2; | ||
| 71 | u32 tlo1 : 5; | ||
| 72 | u32 reserved2 :19; | ||
| 73 | } tw_sm_c_108; | ||
| 74 | |||
| 75 | struct { | ||
| 76 | u32 thi1 : 6; | ||
| 77 | u32 reserved1 : 2; | ||
| 78 | u32 tlo1 : 5; | ||
| 79 | u32 reserved2 :19; | ||
| 80 | } tw_sm_c_10c; | ||
| 81 | |||
| 82 | struct { | ||
| 83 | u32 thi1 : 6; | ||
| 84 | u32 reserved1 : 2; | ||
| 85 | u32 tlo1 : 5; | ||
| 86 | u32 reserved2 :19; | ||
| 87 | } tw_sm_c_110; | ||
| 88 | |||
| 89 | struct { | ||
| 90 | u32 LNB_CTLHighCount_sig :15; | ||
| 91 | u32 LNB_CTLLowCount_sig :15; | ||
| 92 | u32 LNB_CTLPrescaler_sig : 2; | ||
| 93 | } lnb_switch_freq_200; | ||
| 94 | |||
| 95 | struct { | ||
| 96 | u32 ACPI1_sig : 1; | ||
| 97 | u32 ACPI3_sig : 1; | ||
| 98 | u32 LNB_L_H_sig : 1; | ||
| 99 | u32 Per_reset_sig : 1; | ||
| 100 | u32 reserved :20; | ||
| 101 | u32 Rev_N_sig_revision_hi : 4; | ||
| 102 | u32 Rev_N_sig_reserved1 : 2; | ||
| 103 | u32 Rev_N_sig_caps : 1; | ||
| 104 | u32 Rev_N_sig_reserved2 : 1; | ||
| 105 | } misc_204; | ||
| 106 | |||
| 107 | struct { | ||
| 108 | u32 Stream1_filter_sig : 1; | ||
| 109 | u32 Stream2_filter_sig : 1; | ||
| 110 | u32 PCR_filter_sig : 1; | ||
| 111 | u32 PMT_filter_sig : 1; | ||
| 112 | u32 EMM_filter_sig : 1; | ||
| 113 | u32 ECM_filter_sig : 1; | ||
| 114 | u32 Null_filter_sig : 1; | ||
| 115 | u32 Mask_filter_sig : 1; | ||
| 116 | u32 WAN_Enable_sig : 1; | ||
| 117 | u32 WAN_CA_Enable_sig : 1; | ||
| 118 | u32 CA_Enable_sig : 1; | ||
| 119 | u32 SMC_Enable_sig : 1; | ||
| 120 | u32 Per_CA_Enable_sig : 1; | ||
| 121 | u32 Multi2_Enable_sig : 1; | ||
| 122 | u32 MAC_filter_Mode_sig : 1; | ||
| 123 | u32 Rcv_Data_sig : 1; | ||
| 124 | u32 DMA1_IRQ_Enable_sig : 1; | ||
| 125 | u32 DMA1_Timer_Enable_sig : 1; | ||
| 126 | u32 DMA2_IRQ_Enable_sig : 1; | ||
| 127 | u32 DMA2_Timer_Enable_sig : 1; | ||
| 128 | u32 DMA1_Size_IRQ_Enable_sig : 1; | ||
| 129 | u32 DMA2_Size_IRQ_Enable_sig : 1; | ||
| 130 | u32 Mailbox_from_V8_Enable_sig : 1; | ||
| 131 | u32 unused : 9; | ||
| 132 | } ctrl_208; | ||
| 133 | |||
| 134 | struct { | ||
| 135 | u32 DMA1_IRQ_Status : 1; | ||
| 136 | u32 DMA1_Timer_Status : 1; | ||
| 137 | u32 DMA2_IRQ_Status : 1; | ||
| 138 | u32 DMA2_Timer_Status : 1; | ||
| 139 | u32 DMA1_Size_IRQ_Status : 1; | ||
| 140 | u32 DMA2_Size_IRQ_Status : 1; | ||
| 141 | u32 Mailbox_from_V8_Status_sig : 1; | ||
| 142 | u32 Data_receiver_error : 1; | ||
| 143 | u32 Continuity_error_flag : 1; | ||
| 144 | u32 LLC_SNAP_FLAG_set : 1; | ||
| 145 | u32 Transport_Error : 1; | ||
| 146 | u32 reserved :21; | ||
| 147 | } irq_20c; | ||
| 148 | |||
| 149 | struct { | ||
| 150 | u32 reset_block_000 : 1; | ||
| 151 | u32 reset_block_100 : 1; | ||
| 152 | u32 reset_block_200 : 1; | ||
| 153 | u32 reset_block_300 : 1; | ||
| 154 | u32 reset_block_400 : 1; | ||
| 155 | u32 reset_block_500 : 1; | ||
| 156 | u32 reset_block_600 : 1; | ||
| 157 | u32 reset_block_700 : 1; | ||
| 158 | u32 Block_reset_enable : 8; | ||
| 159 | u32 Special_controls :16; | ||
| 160 | } sw_reset_210; | ||
| 161 | |||
| 162 | struct { | ||
| 163 | u32 vuart_oe_sig : 1; | ||
| 164 | u32 v2WS_oe_sig : 1; | ||
| 165 | u32 halt_V8_sig : 1; | ||
| 166 | u32 section_pkg_enable_sig : 1; | ||
| 167 | u32 s2p_sel_sig : 1; | ||
| 168 | u32 unused1 : 3; | ||
| 169 | u32 polarity_PS_CLK_sig : 1; | ||
| 170 | u32 polarity_PS_VALID_sig : 1; | ||
| 171 | u32 polarity_PS_SYNC_sig : 1; | ||
| 172 | u32 polarity_PS_ERR_sig : 1; | ||
| 173 | u32 unused2 :20; | ||
| 174 | } misc_214; | ||
| 175 | |||
| 176 | struct { | ||
| 177 | u32 Mailbox_from_V8 :32; | ||
| 178 | } mbox_v8_to_host_218; | ||
| 179 | |||
| 180 | struct { | ||
| 181 | u32 sysramaccess_data : 8; | ||
| 182 | u32 sysramaccess_addr :15; | ||
| 183 | u32 unused : 7; | ||
| 184 | u32 sysramaccess_write : 1; | ||
| 185 | u32 sysramaccess_busmuster : 1; | ||
| 186 | } mbox_host_to_v8_21c; | ||
| 187 | |||
| 188 | struct { | ||
| 189 | u32 Stream1_PID :13; | ||
| 190 | u32 Stream1_trans : 1; | ||
| 191 | u32 MAC_Multicast_filter : 1; | ||
| 192 | u32 debug_flag_pid_saved : 1; | ||
| 193 | u32 Stream2_PID :13; | ||
| 194 | u32 Stream2_trans : 1; | ||
| 195 | u32 debug_flag_write_status00 : 1; | ||
| 196 | u32 debug_fifo_problem : 1; | ||
| 197 | } pid_filter_300; | ||
| 198 | |||
| 199 | struct { | ||
| 200 | u32 PCR_PID :13; | ||
| 201 | u32 PCR_trans : 1; | ||
| 202 | u32 debug_overrun3 : 1; | ||
| 203 | u32 debug_overrun2 : 1; | ||
| 204 | u32 PMT_PID :13; | ||
| 205 | u32 PMT_trans : 1; | ||
| 206 | u32 reserved : 2; | ||
| 207 | } pid_filter_304; | ||
| 208 | |||
| 209 | struct { | ||
| 210 | u32 EMM_PID :13; | ||
| 211 | u32 EMM_trans : 1; | ||
| 212 | u32 EMM_filter_4 : 1; | ||
| 213 | u32 EMM_filter_6 : 1; | ||
| 214 | u32 ECM_PID :13; | ||
| 215 | u32 ECM_trans : 1; | ||
| 216 | u32 reserved : 2; | ||
| 217 | } pid_filter_308; | ||
| 218 | |||
| 219 | struct { | ||
| 220 | u32 Group_PID :13; | ||
| 221 | u32 Group_trans : 1; | ||
| 222 | u32 unused1 : 2; | ||
| 223 | u32 Group_mask :13; | ||
| 224 | u32 unused2 : 3; | ||
| 225 | } pid_filter_30c_ext_ind_0_7; | ||
| 226 | |||
| 227 | struct { | ||
| 228 | u32 net_master_read :17; | ||
| 229 | u32 unused :15; | ||
| 230 | } pid_filter_30c_ext_ind_1; | ||
| 231 | |||
| 232 | struct { | ||
| 233 | u32 net_master_write :17; | ||
| 234 | u32 unused :15; | ||
| 235 | } pid_filter_30c_ext_ind_2; | ||
| 236 | |||
| 237 | struct { | ||
| 238 | u32 next_net_master_write :17; | ||
| 239 | u32 unused :15; | ||
| 240 | } pid_filter_30c_ext_ind_3; | ||
| 241 | |||
| 242 | struct { | ||
| 243 | u32 unused1 : 1; | ||
| 244 | u32 state_write :10; | ||
| 245 | u32 reserved1 : 6; | ||
| 246 | u32 stack_read :10; | ||
| 247 | u32 reserved2 : 5; | ||
| 248 | } pid_filter_30c_ext_ind_4; | ||
| 249 | |||
| 250 | struct { | ||
| 251 | u32 stack_cnt :10; | ||
| 252 | u32 unused :22; | ||
| 253 | } pid_filter_30c_ext_ind_5; | ||
| 254 | |||
| 255 | struct { | ||
| 256 | u32 pid_fsm_save_reg0 : 2; | ||
| 257 | u32 pid_fsm_save_reg1 : 2; | ||
| 258 | u32 pid_fsm_save_reg2 : 2; | ||
| 259 | u32 pid_fsm_save_reg3 : 2; | ||
| 260 | u32 pid_fsm_save_reg4 : 2; | ||
| 261 | u32 pid_fsm_save_reg300 : 2; | ||
| 262 | u32 write_status1 : 2; | ||
| 263 | u32 write_status4 : 2; | ||
| 264 | u32 data_size_reg :12; | ||
| 265 | u32 unused : 4; | ||
| 266 | } pid_filter_30c_ext_ind_6; | ||
| 267 | |||
| 268 | struct { | ||
| 269 | u32 index_reg : 5; | ||
| 270 | u32 extra_index_reg : 3; | ||
| 271 | u32 AB_select : 1; | ||
| 272 | u32 pass_alltables : 1; | ||
| 273 | u32 unused :22; | ||
| 274 | } index_reg_310; | ||
| 275 | |||
| 276 | struct { | ||
| 277 | u32 PID :13; | ||
| 278 | u32 PID_trans : 1; | ||
| 279 | u32 PID_enable_bit : 1; | ||
| 280 | u32 reserved :17; | ||
| 281 | } pid_n_reg_314; | ||
| 282 | |||
| 283 | struct { | ||
| 284 | u32 A4_byte : 8; | ||
| 285 | u32 A5_byte : 8; | ||
| 286 | u32 A6_byte : 8; | ||
| 287 | u32 Enable_bit : 1; | ||
| 288 | u32 HighAB_bit : 1; | ||
| 289 | u32 reserved : 6; | ||
| 290 | } mac_low_reg_318; | ||
| 291 | |||
| 292 | struct { | ||
| 293 | u32 A1_byte : 8; | ||
| 294 | u32 A2_byte : 8; | ||
| 295 | u32 A3_byte : 8; | ||
| 296 | u32 reserved : 8; | ||
| 297 | } mac_high_reg_31c; | ||
| 298 | |||
| 299 | struct { | ||
| 300 | u32 reserved :16; | ||
| 301 | u32 data_Tag_ID :16; | ||
| 302 | } data_tag_400; | ||
| 303 | |||
| 304 | struct { | ||
| 305 | u32 Card_IDbyte6 : 8; | ||
| 306 | u32 Card_IDbyte5 : 8; | ||
| 307 | u32 Card_IDbyte4 : 8; | ||
| 308 | u32 Card_IDbyte3 : 8; | ||
| 309 | } card_id_408; | ||
| 310 | |||
| 311 | struct { | ||
| 312 | u32 Card_IDbyte2 : 8; | ||
| 313 | u32 Card_IDbyte1 : 8; | ||
| 314 | } card_id_40c; | ||
| 315 | |||
| 316 | struct { | ||
| 317 | u32 MAC1 : 8; | ||
| 318 | u32 MAC2 : 8; | ||
| 319 | u32 MAC3 : 8; | ||
| 320 | u32 MAC6 : 8; | ||
| 321 | } mac_address_418; | ||
| 322 | |||
| 323 | struct { | ||
| 324 | u32 MAC7 : 8; | ||
| 325 | u32 MAC8 : 8; | ||
| 326 | u32 reserved :16; | ||
| 327 | } mac_address_41c; | ||
| 328 | |||
| 329 | struct { | ||
| 330 | u32 transmitter_data_byte : 8; | ||
| 331 | u32 ReceiveDataReady : 1; | ||
| 332 | u32 ReceiveByteFrameError : 1; | ||
| 333 | u32 txbuffempty : 1; | ||
| 334 | u32 reserved :21; | ||
| 335 | } ci_600; | ||
| 336 | |||
| 337 | struct { | ||
| 338 | u32 pi_d : 8; | ||
| 339 | u32 pi_ha :20; | ||
| 340 | u32 pi_rw : 1; | ||
| 341 | u32 pi_component_reg : 3; | ||
| 342 | } pi_604; | ||
| 343 | |||
| 344 | struct { | ||
| 345 | u32 serialReset : 1; | ||
| 346 | u32 oncecycle_read : 1; | ||
| 347 | u32 Timer_Read_req : 1; | ||
| 348 | u32 Timer_Load_req : 1; | ||
| 349 | u32 timer_data : 7; | ||
| 350 | u32 unused : 1; | ||
| 351 | u32 Timer_addr : 5; | ||
| 352 | u32 reserved : 3; | ||
| 353 | u32 pcmcia_a_mod_pwr_n : 1; | ||
| 354 | u32 pcmcia_b_mod_pwr_n : 1; | ||
| 355 | u32 config_Done_stat : 1; | ||
| 356 | u32 config_Init_stat : 1; | ||
| 357 | u32 config_Prog_n : 1; | ||
| 358 | u32 config_wr_n : 1; | ||
| 359 | u32 config_cs_n : 1; | ||
| 360 | u32 config_cclk : 1; | ||
| 361 | u32 pi_CiMax_IRQ_n : 1; | ||
| 362 | u32 pi_timeout_status : 1; | ||
| 363 | u32 pi_wait_n : 1; | ||
| 364 | u32 pi_busy_n : 1; | ||
| 365 | } pi_608; | ||
| 366 | |||
| 367 | struct { | ||
| 368 | u32 PID :13; | ||
| 369 | u32 key_enable : 1; | ||
| 370 | u32 key_code : 2; | ||
| 371 | u32 key_array_col : 3; | ||
| 372 | u32 key_array_row : 5; | ||
| 373 | u32 dvb_en : 1; | ||
| 374 | u32 rw_flag : 1; | ||
| 375 | u32 reserved : 6; | ||
| 376 | } dvb_reg_60c; | ||
| 377 | |||
| 378 | struct { | ||
| 379 | u32 sram_addr :15; | ||
| 380 | u32 sram_rw : 1; | ||
| 381 | u32 sram_data : 8; | ||
| 382 | u32 sc_xfer_bit : 1; | ||
| 383 | u32 reserved1 : 3; | ||
| 384 | u32 oe_pin_reg : 1; | ||
| 385 | u32 ce_pin_reg : 1; | ||
| 386 | u32 reserved2 : 1; | ||
| 387 | u32 start_sram_ibi : 1; | ||
| 388 | } sram_ctrl_reg_700; | ||
| 389 | |||
| 390 | struct { | ||
| 391 | u32 net_addr_read :16; | ||
| 392 | u32 net_addr_write :16; | ||
| 393 | } net_buf_reg_704; | ||
| 394 | |||
| 395 | struct { | ||
| 396 | u32 cai_read :11; | ||
| 397 | u32 reserved1 : 5; | ||
| 398 | u32 cai_write :11; | ||
| 399 | u32 reserved2 : 6; | ||
| 400 | u32 cai_cnt : 4; | ||
| 401 | } cai_buf_reg_708; | ||
| 402 | |||
| 403 | struct { | ||
| 404 | u32 cao_read :11; | ||
| 405 | u32 reserved1 : 5; | ||
| 406 | u32 cap_write :11; | ||
| 407 | u32 reserved2 : 6; | ||
| 408 | u32 cao_cnt : 4; | ||
| 409 | } cao_buf_reg_70c; | ||
| 410 | |||
| 411 | struct { | ||
| 412 | u32 media_read :11; | ||
| 413 | u32 reserved1 : 5; | ||
| 414 | u32 media_write :11; | ||
| 415 | u32 reserved2 : 6; | ||
| 416 | u32 media_cnt : 4; | ||
| 417 | } media_buf_reg_710; | ||
| 418 | |||
| 419 | struct { | ||
| 420 | u32 NET_Dest : 2; | ||
| 421 | u32 CAI_Dest : 2; | ||
| 422 | u32 CAO_Dest : 2; | ||
| 423 | u32 MEDIA_Dest : 2; | ||
| 424 | u32 net_ovflow_error : 1; | ||
| 425 | u32 media_ovflow_error : 1; | ||
| 426 | u32 cai_ovflow_error : 1; | ||
| 427 | u32 cao_ovflow_error : 1; | ||
| 428 | u32 ctrl_usb_wan : 1; | ||
| 429 | u32 ctrl_sramdma : 1; | ||
| 430 | u32 ctrl_maximumfill : 1; | ||
| 431 | u32 reserved :17; | ||
| 432 | } sram_dest_reg_714; | ||
| 433 | |||
| 434 | struct { | ||
| 435 | u32 net_cnt :12; | ||
| 436 | u32 reserved1 : 4; | ||
| 437 | u32 net_addr_read : 1; | ||
| 438 | u32 reserved2 : 3; | ||
| 439 | u32 net_addr_write : 1; | ||
| 440 | u32 reserved3 :11; | ||
| 441 | } net_buf_reg_718; | ||
| 442 | |||
| 443 | struct { | ||
| 444 | u32 wan_speed_sig : 2; | ||
| 445 | u32 reserved1 : 6; | ||
| 446 | u32 wan_wait_state : 8; | ||
| 447 | u32 sram_chip : 2; | ||
| 448 | u32 sram_memmap : 2; | ||
| 449 | u32 reserved2 : 4; | ||
| 450 | u32 wan_pkt_frame : 4; | ||
| 451 | u32 reserved3 : 4; | ||
| 452 | } wan_ctrl_reg_71c; | ||
| 453 | } flexcop_ibi_value; | ||
| 454 | |||
| 455 | #endif | ||
