Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] dvb: b2c2/flexcop driver refactoring part 2: add modular Flexcop driver

b2c2/flexcop driver refactoring to support PCI and USB based cards part 2: add
modular Flexcop driver

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Johannes Stezenbach and committed by
Linus Torvalds
2add87a9 1ec35972

+4098 -1
+279
Documentation/dvb/README.flexcop
··· 1 + This README escorted the skystar2-driver rewriting procedure. It describes the 2 + state of the new flexcop-driver set and some internals are written down here 3 + too. 4 + 5 + How to do something in here? 6 + ============================ 7 + 8 + make -f Makefile.t 9 + make -C ../build-2.6 10 + ./in.sh # load the drivers 11 + ./rm.sh # unload the drivers 12 + 13 + Please read this file, if you want to contribute. 14 + 15 + This document hopefully describes things about the flexcop and its 16 + device-offsprings. Goal is to write a easy-to-write and easy-to-read set of 17 + drivers based on the skystar2.c and other information. 18 + 19 + This directory is temporary. It is used for rewriting the skystar2.c and to 20 + create shared code, which then can be used by the usb box as well. 21 + 22 + Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been 23 + touched and rewritten. 24 + 25 + General coding processing 26 + ========================= 27 + 28 + We should proceed as follows (as long as no one complains): 29 + 30 + 0) Think before start writing code! 31 + 32 + 1) rewriting the skystar2.c with the help of the flexcop register descriptions 33 + and splitting up the files to a pci-bus-part and a flexcop-part. 34 + The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the 35 + device-specific part and b2c2-flexcop.ko for the common flexcop-functions. 36 + 37 + 2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c 38 + and other pci drivers) 39 + 40 + 3) make some beautification (see 'Improvements when rewriting (refactoring) is 41 + done') 42 + 43 + 4) Testing the new driver and maybe substitute the skystar2.c with it, to reach 44 + a wider tester audience. 45 + 46 + 5) creating an usb-bus-part using the already written flexcop code for the pci 47 + card. 48 + 49 + Idea: create a kernel-object for the flexcop and export all important 50 + functions. This option saves kernel-memory, but maybe a lot of functions have 51 + to be exported to kernel namespace. 52 + 53 + 54 + Current situation 55 + ================= 56 + 57 + 0) Done :) 58 + 1) Done (some minor issues left) 59 + 2) Done 60 + 3) Not ready yet, more information is necessary 61 + 4) next to be done (see the table below) 62 + 5) USB driver is working (yes, there are some minor issues) 63 + 64 + What seems to be ready? 65 + ----------------------- 66 + 67 + 1) Rewriting 68 + 1a) i2c is cut off from the flexcop-pci.c and seems to work 69 + 1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c 70 + 1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c 71 + 1e) eeprom (reading MAC address) 72 + 1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me)) 73 + 1f) misc. register accesses for reading parameters (e.g. resetting, revision) 74 + 1g) pid/mac filter (flexcop-hw-filter.c) 75 + 1i) dvb-stuff initialization in flexcop.c (done) 76 + 1h) dma stuff (now just using the size-irq, instead of all-together, to be done) 77 + 1j) remove flexcop initialization from flexcop-pci.c completely (done) 78 + 1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO') 79 + 1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from 80 + non-static where possible, moved code to proper places) 81 + 82 + 2) Search for errors in the leftover of flexcop-pci.c (partially done) 83 + 5a) add MAC address reading 84 + 85 + What to do in the near future? 86 + -------------------------------------- 87 + (no special order here) 88 + 89 + 90 + 5) USB driver 91 + 5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting) 92 + 5c) feeding of ISOC data to the software demux (format of the isochronous data 93 + and speed optimization, no real error) 94 + 95 + Testing changes 96 + --------------- 97 + 98 + O = item is working 99 + P = item is partially working 100 + X = item is not working 101 + N = item does not apply here 102 + <empty field> = item need to be examined 103 + 104 + | PCI | USB 105 + item | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312 106 + -------+-------+---------+---------+-------+-------+---------+---------+------- 107 + 1a) | O | | | | N | N | N | N 108 + 1b) | O | | | | | | O | 109 + 1c) | N | N | | | N | N | O | 110 + 1d) | O | O 111 + 1e) | O | O 112 + 1f) | P 113 + 1g) | O 114 + 1h) | P | 115 + 1i) | O | N 116 + 1j) | O | N 117 + 1l) | O | N 118 + 2) | O | N 119 + 5a) | N | O 120 + 5b)* | N | 121 + 5c)* | N | 122 + 123 + * - not done yet 124 + 125 + Known bugs and problems and TODO 126 + -------------------------------- 127 + 128 + 1g/h/l) when pid filtering is enabled on the pci card 129 + 130 + DMA usage currently: 131 + The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first 132 + address and triggers an IRQ when it's full and starts writing to the second 133 + address. When the second address is full, the IRQ is triggered again, and 134 + the flexcop writes to first address again, and so on. 135 + The buffersize of each address is currently 640*188 bytes. 136 + 137 + Problem is, when using hw-pid-filtering and doing some low-bandwidth 138 + operation (like scanning) the buffers won't be filled enough to trigger 139 + the IRQ. That's why: 140 + 141 + When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ 142 + is triggered. Is the current write address of DMA1 different to the one 143 + during the last IRQ, then the data is passed to the demuxer. 144 + 145 + There is an additional DMA-IRQ-method: packet count IRQ. This isn't 146 + implemented correctly yet. 147 + 148 + The solution is to disable HW PID filtering, but I don't know how the DVB 149 + API software demux behaves on slow systems with 45MBit/s TS. 150 + 151 + Solved bugs :) 152 + -------------- 153 + 1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't 154 + working) 155 + SOLUTION: also index 0 was affected, because net_translation is done for 156 + these indexes by default 157 + 158 + 5b) isochronous transfer does only work in the first attempt (for the Sky2PC USB, 159 + Air2PC is working) 160 + SOLUTION: the flexcop was going asleep and never really woke up again (don't 161 + know if this need fixes, see flexcop-fe-tuner.c:flexcop_sleep) 162 + 163 + Improvements when rewriting (refactoring) is done 164 + ================================================= 165 + 166 + - split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control 167 + (enable sleeping for other demods than dvb-s) 168 + - add support for CableStar (stv0297 Microtune 203x/ALPS) 169 + 170 + Debugging 171 + --------- 172 + - add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it 173 + with this flexcop, this is important, because i2c is now using the 174 + flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for 175 + that, please tell us so). 176 + 177 + Everything which is identical in the following table, can be put into a common 178 + flexcop-module. 179 + 180 + PCI USB 181 + ------------------------------------------------------------------------------- 182 + Different: 183 + Register access: accessing IO memory USB control message 184 + I2C bus: I2C bus of the FC USB control message 185 + Data transfer: DMA isochronous transfer 186 + EEPROM transfer: through i2c bus not clear yet 187 + 188 + Identical: 189 + Streaming: accessing registers 190 + PID Filtering: accessing registers 191 + Sram destinations: accessing registers 192 + Tuner/Demod: I2C bus 193 + DVB-stuff: can be written for common use 194 + 195 + Restrictions: 196 + ============ 197 + 198 + We need to create a bus-specific-struct and a flexcop-struct. 199 + 200 + bus-specific-struct: 201 + 202 + struct flexcop_pci 203 + ... 204 + 205 + struct flexcop_usb 206 + ... 207 + 208 + 209 + struct flexcop_device { 210 + void *bus_specific; /* container for bus-specific struct */ 211 + ... 212 + } 213 + 214 + PCI i2c can read/write max 4 bytes at a time, USB can more 215 + 216 + Functions 217 + ========= 218 + 219 + Syntax 220 + ------ 221 + 222 + - Flexcop functions will be called "flexcop(_[a-z0-9]+)+" and exported as such 223 + if needed. 224 + - Flexcop-device functions will be called "flexcop_device(_[a-z0-9]+)+" and 225 + exported as such if needed. 226 + - Both will be compiled to b2c2-flexcop.ko and their source can be found in the 227 + flexcop*.[hc] 228 + 229 + Callbacks and exports 230 + --------------------- 231 + 232 + Bus-specific functions will be given as callbacks (function pointers) to the 233 + flexcop-module. (within the flexcop_device-struct) 234 + 235 + Initialization process 236 + ====================== 237 + 238 + b2c2-flexcop.ko is loaded 239 + b2c2-flexcop-<bus>.ko is loaded 240 + 241 + suppose a device is found: 242 + malloc flexcop and the bus-specific variables (via flexcop_device_malloc) 243 + fill the bus-specific variable 244 + fill the flexcop variable (especially the bus-specific callbacks) 245 + bus-specific initialization 246 + - ... 247 + do the common initialization (via flexcop_device_initialize) 248 + - reset the card 249 + - determine flexcop type (II, IIB, III) 250 + - hw_filters (bus dependent) 251 + - 0x204 252 + - set sram size 253 + - create the dvb-stuff 254 + - create i2c stuff 255 + - frontend-initialization 256 + done 257 + bus specific: 258 + - media_destination (this and the following 3 are bus specific) 259 + - cai_dest 260 + - cao_dest 261 + - net_destination 262 + 263 + Bugs fixed while rewriting the driver 264 + ===================================== 265 + 266 + - EEPROM access (to read the MAC address) was fixed to death some time last 267 + year. (fixed here and in skystar2.c) (Bjarne, this was the piece of code 268 + (fix-chipaddr) we were wondering about) 269 + 270 + 271 + Acknowledgements (just for the rewriting part) 272 + ================ 273 + 274 + Bjarne Steinsbo thought a lot in the first place of the pci part for this code 275 + sharing idea. 276 + 277 + Andreas Oberritter for providing a recent PCI initialization template (pluto2.c). 278 + 279 + comments, critics and ideas to linux-dvb@linuxtv.org or patrick.boettcher@desy.de
+1 -1
drivers/media/dvb/Kconfig
··· 33 33 source "drivers/media/dvb/cinergyT2/Kconfig" 34 34 35 35 comment "Supported FlexCopII (B2C2) Adapters" 36 - depends on DVB_CORE && PCI 36 + depends on DVB_CORE && (PCI || USB) 37 37 source "drivers/media/dvb/b2c2/Kconfig" 38 38 39 39 comment "Supported BT878 Adapters"
+37
drivers/media/dvb/b2c2/Kconfig
··· 1 + config DVB_B2C2_FLEXCOP 2 + tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" 3 + depends on DVB_CORE 4 + select DVB_STV0299 5 + select DVB_MT352 6 + select DVB_MT312 7 + select DVB_NXT2002 8 + select DVB_STV0297 9 + help 10 + Support for the digital TV receiver chip made by B2C2 Inc. included in 11 + Technisats PCI cards and USB boxes. 12 + 13 + Say Y if you own such a device and want to use it. 14 + 15 + config DVB_B2C2_FLEXCOP_PCI 16 + tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI" 17 + depends on DVB_B2C2_FLEXCOP && PCI 18 + help 19 + Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2. 20 + 21 + Say Y if you own such a device and want to use it. 22 + 23 + config DVB_B2C2_FLEXCOP_USB 24 + tristate "Technisat/B2C2 Air/Sky/Cable2PC USB" 25 + depends on DVB_B2C2_FLEXCOP && USB 26 + help 27 + Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2, 28 + 29 + Say Y if you own such a device and want to use it. 30 + 31 + config DVB_B2C2_FLEXCOP_DEBUG 32 + bool "Enable debug for the B2C2 FlexCop drivers" 33 + depends on DVB_B2C2_FLEXCOP 34 + help 35 + Say Y if you want to enable the module option to control debug messages 36 + of all B2C2 FlexCop drivers. 37 + 1 38 config DVB_B2C2_SKYSTAR 2 39 tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI" 3 40 depends on DVB_CORE && PCI
+11
drivers/media/dvb/b2c2/Makefile
··· 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 + flexcop-dma.o 4 + obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o 5 + 6 + b2c2-flexcop-pci-objs = flexcop-pci.o 7 + obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o 8 + 9 + b2c2-flexcop-usb-objs = flexcop-usb.o 10 + obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o 11 + 1 12 obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o 2 13 3 14 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+161
drivers/media/dvb/b2c2/flexcop-common.h
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-common.h - common header file for device-specific source files also. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #ifndef __FLEXCOP_COMMON_H__ 9 + #define __FLEXCOP_COMMON_H__ 10 + 11 + #include <linux/config.h> 12 + #include <linux/pci.h> 13 + 14 + #include "flexcop-reg.h" 15 + 16 + #include "dmxdev.h" 17 + #include "dvb_demux.h" 18 + #include "dvb_filter.h" 19 + #include "dvb_net.h" 20 + #include "dvb_frontend.h" 21 + 22 + #define FC_MAX_FEED 256 23 + 24 + #ifndef FC_LOG_PREFIX 25 + #warning please define a log prefix for your file, using a default one 26 + #define FC_LOG_PREFIX "b2c2-undef" 27 + #endif 28 + 29 + /* Steal from usb.h */ 30 + #undef err 31 + #define err(format, arg...) printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg) 32 + #undef info 33 + #define info(format, arg...) printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg) 34 + #undef warn 35 + #define warn(format, arg...) printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg) 36 + 37 + struct flexcop_dma { 38 + struct pci_dev *pdev; 39 + 40 + u8 *cpu_addr0; 41 + dma_addr_t dma_addr0; 42 + u8 *cpu_addr1; 43 + dma_addr_t dma_addr1; 44 + u32 size; /* size of each address in bytes */ 45 + }; 46 + 47 + /* Control structure for data definitions that are common to 48 + * the B2C2-based PCI and USB devices. 49 + */ 50 + struct flexcop_device { 51 + /* general */ 52 + struct device *dev; /* for firmware_class */ 53 + 54 + #define FC_STATE_DVB_INIT 0x01 55 + #define FC_STATE_I2C_INIT 0x02 56 + #define FC_STATE_FE_INIT 0x04 57 + int init_state; 58 + 59 + /* device information */ 60 + u8 mac_address[6]; 61 + int has_32_hw_pid_filter; 62 + flexcop_revision_t rev; 63 + flexcop_device_type_t dev_type; 64 + flexcop_bus_t bus_type; 65 + 66 + /* dvb stuff */ 67 + struct dvb_adapter dvb_adapter; 68 + struct dvb_frontend *fe; 69 + struct dvb_net dvbnet; 70 + struct dvb_demux demux; 71 + struct dmxdev dmxdev; 72 + struct dmx_frontend hw_frontend; 73 + struct dmx_frontend mem_frontend; 74 + int (*fe_sleep) (struct dvb_frontend *); 75 + 76 + struct i2c_adapter i2c_adap; 77 + struct semaphore i2c_sem; 78 + 79 + /* options and status */ 80 + int feedcount; 81 + int pid_filtering; 82 + 83 + /* bus specific callbacks */ 84 + flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register); 85 + int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value); 86 + 87 + 88 + int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); 89 + int (*stream_control) (struct flexcop_device*, int); 90 + 91 + int (*get_mac_addr) (struct flexcop_device *fc, int extended); 92 + 93 + void *bus_specific; 94 + }; 95 + 96 + /* exported prototypes */ 97 + 98 + /* from flexcop.c */ 99 + void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len); 100 + void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no); 101 + 102 + struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len); 103 + void flexcop_device_kfree(struct flexcop_device*); 104 + 105 + int flexcop_device_initialize(struct flexcop_device*); 106 + void flexcop_device_exit(struct flexcop_device *fc); 107 + 108 + /* from flexcop-dma.c */ 109 + int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size); 110 + void flexcop_dma_free(struct flexcop_dma *dma); 111 + 112 + int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); 113 + int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); 114 + int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); 115 + int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index); 116 + int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); 117 + int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets); 118 + 119 + /* from flexcop-eeprom.c */ 120 + /* the PCI part uses this call to get the MAC address, the USB part has its own */ 121 + int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended); 122 + 123 + /* from flexcop-i2c.c */ 124 + /* the PCI part uses this a i2c_request callback, whereas the usb part has its own 125 + * one. We have it in flexcop-i2c.c, because it is going via the actual 126 + * I2C-channel of the flexcop. 127 + */ 128 + int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t, 129 + flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); 130 + 131 + /* from flexcop-sram.c */ 132 + int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target); 133 + void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s); 134 + void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill); 135 + 136 + /* global prototypes for the flexcop-chip */ 137 + /* from flexcop-fe-tuner.c */ 138 + int flexcop_frontend_init(struct flexcop_device *card); 139 + void flexcop_frontend_exit(struct flexcop_device *fc); 140 + 141 + /* from flexcop-i2c.c */ 142 + int flexcop_i2c_init(struct flexcop_device *fc); 143 + void flexcop_i2c_exit(struct flexcop_device *fc); 144 + 145 + /* from flexcop-sram.c */ 146 + int flexcop_sram_init(struct flexcop_device *fc); 147 + 148 + /* from flexcop-misc.c */ 149 + void flexcop_determine_revision(struct flexcop_device *fc); 150 + void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix); 151 + 152 + /* from flexcop-hw-filter.c */ 153 + int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff); 154 + void flexcop_hw_filter_init(struct flexcop_device *fc); 155 + 156 + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); 157 + 158 + void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); 159 + void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff); 160 + 161 + #endif
+149
drivers/media/dvb/b2c2/flexcop-dma.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size) 11 + { 12 + u8 *tcpu; 13 + dma_addr_t tdma; 14 + 15 + if (size % 2) { 16 + err("dma buffersize has to be even."); 17 + return -EINVAL; 18 + } 19 + 20 + if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) { 21 + dma->pdev = pdev; 22 + dma->cpu_addr0 = tcpu; 23 + dma->dma_addr0 = tdma; 24 + dma->cpu_addr1 = tcpu + size/2; 25 + dma->dma_addr1 = tdma + size/2; 26 + dma->size = size/2; 27 + return 0; 28 + } 29 + return -ENOMEM; 30 + } 31 + EXPORT_SYMBOL(flexcop_dma_allocate); 32 + 33 + void flexcop_dma_free(struct flexcop_dma *dma) 34 + { 35 + pci_free_consistent(dma->pdev, dma->size*2,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_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 41 + { 42 + flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 43 + 44 + if (no & FC_DMA_1) 45 + v.ctrl_208.DMA1_Timer_Enable_sig = onoff; 46 + 47 + if (no & FC_DMA_2) 48 + v.ctrl_208.DMA2_Timer_Enable_sig = onoff; 49 + 50 + fc->write_ibi_reg(fc,ctrl_208,v); 51 + return 0; 52 + } 53 + EXPORT_SYMBOL(flexcop_dma_control_timer_irq); 54 + 55 + int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 56 + { 57 + flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 58 + 59 + if (no & FC_DMA_1) 60 + v.ctrl_208.DMA1_IRQ_Enable_sig = onoff; 61 + 62 + if (no & FC_DMA_2) 63 + v.ctrl_208.DMA2_IRQ_Enable_sig = onoff; 64 + 65 + fc->write_ibi_reg(fc,ctrl_208,v); 66 + return 0; 67 + } 68 + EXPORT_SYMBOL(flexcop_dma_control_size_irq); 69 + 70 + int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff) 71 + { 72 + flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); 73 + 74 + if (no & FC_DMA_1) 75 + v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff; 76 + 77 + if (no & FC_DMA_2) 78 + v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff; 79 + 80 + fc->write_ibi_reg(fc,ctrl_208,v); 81 + return 0; 82 + } 83 + EXPORT_SYMBOL(flexcop_dma_control_packet_irq); 84 + 85 + int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index) 86 + { 87 + 88 + flexcop_ibi_value v0x0,v0x4,v0xc; 89 + v0x0.raw = v0x4.raw = v0xc.raw = 0; 90 + 91 + v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; 92 + v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; 93 + v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; 94 + 95 + if (index & FC_DMA_SUBADDR_0) 96 + v0x0.dma_0x0.dma_0start = 1; 97 + 98 + if (index & FC_DMA_SUBADDR_1) 99 + v0xc.dma_0xc.dma_1start = 1; 100 + 101 + if (dma_idx & FC_DMA_1) { 102 + fc->write_ibi_reg(fc,dma1_000,v0x0); 103 + fc->write_ibi_reg(fc,dma1_004,v0x4); 104 + fc->write_ibi_reg(fc,dma1_00c,v0xc); 105 + } else { /* (dma_idx & FC_DMA_2) */ 106 + fc->write_ibi_reg(fc,dma2_010,v0x0); 107 + fc->write_ibi_reg(fc,dma2_014,v0x4); 108 + fc->write_ibi_reg(fc,dma2_01c,v0xc); 109 + } 110 + 111 + return 0; 112 + } 113 + EXPORT_SYMBOL(flexcop_dma_config); 114 + 115 + static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, int onoff) 116 + { 117 + flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; 118 + flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 119 + v.dma_0xc.remap_enable = onoff; 120 + fc->write_ibi_reg(fc,r,v); 121 + return 0; 122 + } 123 + 124 + /* 1 cycles = 1.97 msec */ 125 + int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles) 126 + { 127 + flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 128 + flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 129 + 130 + flexcop_dma_remap(fc,dma_idx,0); 131 + 132 + v.dma_0x4_write.dmatimer = cycles >> 1; 133 + fc->write_ibi_reg(fc,r,v); 134 + return 0; 135 + } 136 + EXPORT_SYMBOL(flexcop_dma_config_timer); 137 + 138 + int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets) 139 + { 140 + flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; 141 + flexcop_ibi_value v = fc->read_ibi_reg(fc,r); 142 + 143 + flexcop_dma_remap(fc,dma_idx,1); 144 + 145 + v.dma_0x4_remap.DMA_maxpackets = packets; 146 + fc->write_ibi_reg(fc,r,v); 147 + return 0; 148 + } 149 + EXPORT_SYMBOL(flexcop_dma_config_packet_count);
+157
drivers/media/dvb/b2c2/flexcop-eeprom.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used) 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + #if 0 11 + /*EEPROM (Skystar2 has one "24LC08B" chip on board) */ 12 + static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len) 13 + { 14 + return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len); 15 + } 16 + 17 + static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries) 18 + { 19 + int i; 20 + 21 + for (i = 0; i < retries; i++) { 22 + if (eeprom_write(adapter, addr, wbuf, len) == len) { 23 + if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1) 24 + return 1; 25 + } 26 + } 27 + 28 + return 0; 29 + } 30 + 31 + /* These functions could be used to unlock SkyStar2 cards. */ 32 + 33 + static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len) 34 + { 35 + u8 rbuf[20]; 36 + u8 wbuf[20]; 37 + 38 + if (len != 16) 39 + return 0; 40 + 41 + memcpy(wbuf, key, len); 42 + 43 + wbuf[16] = 0; 44 + wbuf[17] = 0; 45 + wbuf[18] = 0; 46 + wbuf[19] = calc_lrc(wbuf, 19); 47 + 48 + return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4); 49 + } 50 + 51 + static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len) 52 + { 53 + u8 buf[20]; 54 + 55 + if (len != 16) 56 + return 0; 57 + 58 + if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0) 59 + return 0; 60 + 61 + memcpy(key, buf, len); 62 + 63 + return 1; 64 + } 65 + 66 + static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac) 67 + { 68 + u8 tmp[8]; 69 + 70 + if (type != 0) { 71 + tmp[0] = mac[0]; 72 + tmp[1] = mac[1]; 73 + tmp[2] = mac[2]; 74 + tmp[3] = mac[5]; 75 + tmp[4] = mac[6]; 76 + tmp[5] = mac[7]; 77 + 78 + } else { 79 + 80 + tmp[0] = mac[0]; 81 + tmp[1] = mac[1]; 82 + tmp[2] = mac[2]; 83 + tmp[3] = mac[3]; 84 + tmp[4] = mac[4]; 85 + tmp[5] = mac[5]; 86 + } 87 + 88 + tmp[6] = 0; 89 + tmp[7] = calc_lrc(tmp, 7); 90 + 91 + if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8) 92 + return 1; 93 + 94 + return 0; 95 + } 96 + 97 + static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len) 98 + { 99 + return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len); 100 + } 101 + 102 + #endif 103 + 104 + static u8 calc_lrc(u8 *buf, int len) 105 + { 106 + int i; 107 + u8 sum = 0; 108 + for (i = 0; i < len; i++) 109 + sum = sum ^ buf[i]; 110 + return sum; 111 + } 112 + 113 + static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) 114 + { 115 + int i,ret = 0; 116 + u8 chipaddr = 0x50 | ((addr >> 8) & 3); 117 + for (i = 0; i < retries; i++) 118 + if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0) 119 + break; 120 + return ret; 121 + } 122 + 123 + static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries) 124 + { 125 + int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries); 126 + if (ret == 0) 127 + if (calc_lrc(buf, len - 1) != buf[len - 1]) 128 + ret = -EINVAL; 129 + return ret; 130 + } 131 + 132 + /* TODO how is it handled in USB */ 133 + 134 + /* JJ's comment about extended == 1: it is not presently used anywhere but was 135 + * added to the low-level functions for possible support of EUI64 136 + */ 137 + int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) 138 + { 139 + u8 buf[8]; 140 + int ret = 0; 141 + 142 + memset(fc->mac_address,0,6); 143 + 144 + if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) { 145 + if (extended != 0) { 146 + err("TODO: extended (EUI64) MAC addresses aren't completely supported yet"); 147 + ret = -EINVAL; 148 + /* memcpy(fc->mac_address,buf,3); 149 + mac[3] = 0xfe; 150 + mac[4] = 0xff; 151 + memcpy(&fc->mac_address[3],&buf[5],3); */ 152 + } else 153 + memcpy(fc->mac_address,buf,6); 154 + } 155 + return ret; 156 + } 157 + EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
+403
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + #include "stv0299.h" 11 + #include "mt352.h" 12 + #include "nxt2002.h" 13 + #include "stv0297.h" 14 + #include "mt312.h" 15 + 16 + /* lnb control */ 17 + 18 + static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 19 + { 20 + struct flexcop_device *fc = fe->dvb->priv; 21 + flexcop_ibi_value v; 22 + deb_tuner("polarity/voltage = %u\n", voltage); 23 + 24 + v = fc->read_ibi_reg(fc, misc_204); 25 + switch (voltage) { 26 + case SEC_VOLTAGE_OFF: 27 + v.misc_204.ACPI1_sig = 1; 28 + break; 29 + case SEC_VOLTAGE_13: 30 + v.misc_204.ACPI1_sig = 0; 31 + v.misc_204.LNB_L_H_sig = 0; 32 + break; 33 + case SEC_VOLTAGE_18: 34 + v.misc_204.ACPI1_sig = 0; 35 + v.misc_204.LNB_L_H_sig = 1; 36 + break; 37 + default: 38 + err("unknown SEC_VOLTAGE value"); 39 + return -EINVAL; 40 + } 41 + return fc->write_ibi_reg(fc, misc_204, v); 42 + } 43 + 44 + static int flexcop_sleep(struct dvb_frontend* fe) 45 + { 46 + struct flexcop_device *fc = fe->dvb->priv; 47 + /* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */ 48 + 49 + if (fc->fe_sleep) 50 + return fc->fe_sleep(fe); 51 + 52 + /* v.misc_204.ACPI3_sig = 1; 53 + fc->write_ibi_reg(fc,misc_204,v);*/ 54 + 55 + return 0; 56 + } 57 + 58 + static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) 59 + { 60 + /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ 61 + struct flexcop_device *fc = fe->dvb->priv; 62 + flexcop_ibi_value v; 63 + u16 ax; 64 + v.raw = 0; 65 + 66 + deb_tuner("tone = %u\n",tone); 67 + 68 + switch (tone) { 69 + case SEC_TONE_ON: 70 + ax = 0x01ff; 71 + break; 72 + case SEC_TONE_OFF: 73 + ax = 0; 74 + break; 75 + default: 76 + err("unknown SEC_TONE value"); 77 + return -EINVAL; 78 + } 79 + 80 + v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */ 81 + 82 + v.lnb_switch_freq_200.LNB_CTLHighCount_sig = 83 + v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax; 84 + 85 + return fc->write_ibi_reg(fc,lnb_switch_freq_200,v); 86 + } 87 + 88 + static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data) 89 + { 90 + flexcop_set_tone(fe, SEC_TONE_ON); 91 + udelay(data ? 500 : 1000); 92 + flexcop_set_tone(fe, SEC_TONE_OFF); 93 + udelay(data ? 1000 : 500); 94 + } 95 + 96 + static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data) 97 + { 98 + int i, par = 1, d; 99 + 100 + for (i = 7; i >= 0; i--) { 101 + d = (data >> i) & 1; 102 + par ^= d; 103 + flexcop_diseqc_send_bit(fe, d); 104 + } 105 + 106 + flexcop_diseqc_send_bit(fe, par); 107 + } 108 + 109 + static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst) 110 + { 111 + int i; 112 + 113 + flexcop_set_tone(fe, SEC_TONE_OFF); 114 + mdelay(16); 115 + 116 + for (i = 0; i < len; i++) 117 + flexcop_diseqc_send_byte(fe,msg[i]); 118 + 119 + mdelay(16); 120 + 121 + if (burst != -1) { 122 + if (burst) 123 + flexcop_diseqc_send_byte(fe, 0xff); 124 + else { 125 + flexcop_set_tone(fe, SEC_TONE_ON); 126 + udelay(12500); 127 + flexcop_set_tone(fe, SEC_TONE_OFF); 128 + } 129 + msleep(20); 130 + } 131 + return 0; 132 + } 133 + 134 + static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) 135 + { 136 + return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0); 137 + } 138 + 139 + static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) 140 + { 141 + return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd); 142 + } 143 + 144 + /* dvb-s stv0299 */ 145 + static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) 146 + { 147 + u8 aclk = 0; 148 + u8 bclk = 0; 149 + 150 + if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } 151 + else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } 152 + else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } 153 + else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } 154 + else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } 155 + else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } 156 + 157 + stv0299_writereg (fe, 0x13, aclk); 158 + stv0299_writereg (fe, 0x14, bclk); 159 + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); 160 + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); 161 + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); 162 + 163 + return 0; 164 + } 165 + 166 + static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 167 + { 168 + u8 buf[4]; 169 + u32 div; 170 + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 171 + struct flexcop_device *fc = fe->dvb->priv; 172 + 173 + div = params->frequency / 125; 174 + 175 + buf[0] = (div >> 8) & 0x7f; 176 + buf[1] = div & 0xff; 177 + buf[2] = 0x84; /* 0xC4 */ 178 + buf[3] = 0x08; 179 + 180 + if (params->frequency < 1500000) buf[3] |= 0x10; 181 + 182 + if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) 183 + return -EIO; 184 + return 0; 185 + } 186 + 187 + static u8 samsung_tbmu24112_inittab[] = { 188 + 0x01, 0x15, 189 + 0x02, 0x30, 190 + 0x03, 0x00, 191 + 0x04, 0x7D, 192 + 0x05, 0x35, 193 + 0x06, 0x02, 194 + 0x07, 0x00, 195 + 0x08, 0xC3, 196 + 0x0C, 0x00, 197 + 0x0D, 0x81, 198 + 0x0E, 0x23, 199 + 0x0F, 0x12, 200 + 0x10, 0x7E, 201 + 0x11, 0x84, 202 + 0x12, 0xB9, 203 + 0x13, 0x88, 204 + 0x14, 0x89, 205 + 0x15, 0xC9, 206 + 0x16, 0x00, 207 + 0x17, 0x5C, 208 + 0x18, 0x00, 209 + 0x19, 0x00, 210 + 0x1A, 0x00, 211 + 0x1C, 0x00, 212 + 0x1D, 0x00, 213 + 0x1E, 0x00, 214 + 0x1F, 0x3A, 215 + 0x20, 0x2E, 216 + 0x21, 0x80, 217 + 0x22, 0xFF, 218 + 0x23, 0xC1, 219 + 0x28, 0x00, 220 + 0x29, 0x1E, 221 + 0x2A, 0x14, 222 + 0x2B, 0x0F, 223 + 0x2C, 0x09, 224 + 0x2D, 0x05, 225 + 0x31, 0x1F, 226 + 0x32, 0x19, 227 + 0x33, 0xFE, 228 + 0x34, 0x93, 229 + 0xff, 0xff, 230 + }; 231 + 232 + static struct stv0299_config samsung_tbmu24112_config = { 233 + .demod_address = 0x68, 234 + .inittab = samsung_tbmu24112_inittab, 235 + .mclk = 88000000UL, 236 + .invert = 0, 237 + .enhanced_tuning = 0, 238 + .skip_reinit = 0, 239 + .lock_output = STV0229_LOCKOUTPUT_LK, 240 + .volt13_op0_op1 = STV0299_VOLT13_OP1, 241 + .min_delay_ms = 100, 242 + .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, 243 + .pll_set = samsung_tbmu24112_pll_set, 244 + }; 245 + 246 + /* dvb-t mt352 */ 247 + static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) 248 + { 249 + static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d }; 250 + static u8 mt352_reset [] = { 0x50, 0x80 }; 251 + static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; 252 + static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 }; 253 + static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; 254 + 255 + mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); 256 + udelay(2000); 257 + mt352_write(fe, mt352_reset, sizeof(mt352_reset)); 258 + mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); 259 + 260 + mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); 261 + mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); 262 + 263 + return 0; 264 + } 265 + 266 + static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) 267 + { 268 + u32 div; 269 + unsigned char bs = 0; 270 + 271 + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ 272 + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; 273 + 274 + if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09; 275 + if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; 276 + if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; 277 + 278 + pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */ 279 + pllbuf[1] = div >> 8; 280 + pllbuf[2] = div & 0xff; 281 + pllbuf[3] = 0xcc; 282 + pllbuf[4] = bs; 283 + 284 + return 0; 285 + } 286 + 287 + static struct mt352_config samsung_tdtc9251dh0_config = { 288 + 289 + .demod_address = 0x0f, 290 + .demod_init = samsung_tdtc9251dh0_demod_init, 291 + .pll_set = samsung_tdtc9251dh0_pll_set, 292 + }; 293 + 294 + static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) 295 + { 296 + struct flexcop_device *fc = fe->dvb->priv; 297 + return request_firmware(fw, name, fc->dev); 298 + } 299 + 300 + static struct nxt2002_config samsung_tbmv_config = { 301 + .demod_address = 0x0a, 302 + .request_firmware = nxt2002_request_firmware, 303 + }; 304 + 305 + static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 306 + { 307 + u8 buf[4]; 308 + u32 div; 309 + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 310 + struct flexcop_device *fc = fe->dvb->priv; 311 + 312 + div = (params->frequency + (125/2)) / 125; 313 + 314 + buf[0] = (div >> 8) & 0x7f; 315 + buf[1] = (div >> 0) & 0xff; 316 + buf[2] = 0x84 | ((div >> 10) & 0x60); 317 + buf[3] = 0x80; 318 + 319 + if (params->frequency < 1550000) 320 + buf[3] |= 0x02; 321 + 322 + if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) 323 + return -EIO; 324 + return 0; 325 + } 326 + 327 + static struct mt312_config skystar23_samsung_tbdu18132_config = { 328 + 329 + .demod_address = 0x0e, 330 + .pll_set = skystar23_samsung_tbdu18132_pll_set, 331 + }; 332 + 333 + static struct stv0297_config alps_tdee4_stv0297_config = { 334 + .demod_address = 0x1c, 335 + // .invert = 1, 336 + // .pll_set = alps_tdee4_stv0297_pll_set, 337 + }; 338 + 339 + /* try to figure out the frontend, each card/box can have on of the following list */ 340 + int flexcop_frontend_init(struct flexcop_device *fc) 341 + { 342 + /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ 343 + if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { 344 + fc->fe->ops->set_voltage = flexcop_set_voltage; 345 + 346 + fc->fe_sleep = fc->fe->ops->sleep; 347 + fc->fe->ops->sleep = flexcop_sleep; 348 + 349 + fc->dev_type = FC_SKY; 350 + info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address); 351 + } else 352 + /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ 353 + if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) { 354 + fc->dev_type = FC_AIR_DVB; 355 + info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); 356 + } else 357 + /* try the air atsc (nxt2002) */ 358 + if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { 359 + fc->dev_type = FC_AIR_ATSC; 360 + info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); 361 + } else 362 + /* try the cable dvb (stv0297) */ 363 + if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) { 364 + fc->dev_type = FC_CABLE; 365 + info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); 366 + } else 367 + /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ 368 + if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { 369 + fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; 370 + fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst; 371 + fc->fe->ops->set_tone = flexcop_set_tone; 372 + fc->fe->ops->set_voltage = flexcop_set_voltage; 373 + 374 + fc->fe_sleep = fc->fe->ops->sleep; 375 + fc->fe->ops->sleep = flexcop_sleep; 376 + 377 + fc->dev_type = FC_SKY_OLD; 378 + info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address); 379 + } 380 + 381 + if (fc->fe == NULL) { 382 + err("no frontend driver found for this B2C2/FlexCop adapter"); 383 + return -ENODEV; 384 + } else { 385 + if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { 386 + err("frontend registration failed!"); 387 + if (fc->fe->ops->release != NULL) 388 + fc->fe->ops->release(fc->fe); 389 + fc->fe = NULL; 390 + return -EINVAL; 391 + } 392 + } 393 + fc->init_state |= FC_STATE_FE_INIT; 394 + return 0; 395 + } 396 + 397 + void flexcop_frontend_exit(struct flexcop_device *fc) 398 + { 399 + if (fc->init_state & FC_STATE_FE_INIT) 400 + dvb_unregister_frontend(fc->fe); 401 + 402 + fc->init_state &= ~FC_STATE_FE_INIT; 403 + }
+198
drivers/media/dvb/b2c2/flexcop-hw-filter.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) 11 + { 12 + flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff); 13 + } 14 + 15 + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) 16 + { 17 + flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff); 18 + } 19 + 20 + void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff) 21 + { 22 + flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff); 23 + } 24 + 25 + void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]) 26 + { 27 + flexcop_ibi_value v418,v41c; 28 + v41c = fc->read_ibi_reg(fc,mac_address_41c); 29 + 30 + v418.mac_address_418.MAC1 = mac[0]; 31 + v418.mac_address_418.MAC2 = mac[1]; 32 + v418.mac_address_418.MAC3 = mac[2]; 33 + v418.mac_address_418.MAC6 = mac[3]; 34 + v41c.mac_address_41c.MAC7 = mac[4]; 35 + v41c.mac_address_41c.MAC8 = mac[5]; 36 + 37 + fc->write_ibi_reg(fc,mac_address_418,v418); 38 + fc->write_ibi_reg(fc,mac_address_41c,v41c); 39 + } 40 + 41 + void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff) 42 + { 43 + flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff); 44 + } 45 + 46 + static void flexcop_pid_group_filter(struct flexcop_device *fc, 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 + \ 68 + vpid.vregname.field = onoff ? pid : 0x1fff; \ 69 + vpid.vregname.trans_field = transval; \ 70 + v208.ctrl_208.enablefield = onoff; \ 71 + \ 72 + fc->write_ibi_reg(fc,vregname,vpid); \ 73 + fc->write_ibi_reg(fc,ctrl_208,v208); 74 + 75 + static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) 76 + { 77 + pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0); 78 + } 79 + 80 + static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) 81 + { 82 + pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0); 83 + } 84 + 85 + static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) 86 + { 87 + pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0); 88 + } 89 + 90 + static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) 91 + { 92 + pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0); 93 + } 94 + 95 + static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) 96 + { 97 + pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0); 98 + } 99 + 100 + static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) 101 + { 102 + pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0); 103 + } 104 + 105 + static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff) 106 + { 107 + deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off"); 108 + 109 + /* We could use bit magic here to reduce source code size. 110 + * I decided against it, but to use the real register names */ 111 + switch (index) { 112 + case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break; 113 + case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break; 114 + case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break; 115 + case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break; 116 + case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break; 117 + case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break; 118 + default: 119 + if (fc->has_32_hw_pid_filter && index < 38) { 120 + flexcop_ibi_value vpid,vid; 121 + 122 + /* set the index */ 123 + vid = fc->read_ibi_reg(fc,index_reg_310); 124 + vid.index_reg_310.index_reg = index - 6; 125 + fc->write_ibi_reg(fc,index_reg_310, vid); 126 + 127 + vpid = fc->read_ibi_reg(fc,pid_n_reg_314); 128 + vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; 129 + vpid.pid_n_reg_314.PID_enable_bit = onoff; 130 + fc->write_ibi_reg(fc,pid_n_reg_314, vpid); 131 + } 132 + break; 133 + } 134 + } 135 + 136 + int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff) 137 + { 138 + int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32; 139 + 140 + fc->feedcount += (onoff ? 1 : -1); 141 + 142 + /* when doing hw pid filtering, set the pid */ 143 + if (fc->pid_filtering) 144 + flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); 145 + 146 + /* if it was the first feed request */ 147 + if (fc->feedcount == onoff && onoff) { 148 + if (!fc->pid_filtering) { 149 + deb_ts("enabling full TS transfer\n"); 150 + flexcop_pid_group_filter(fc, 0,0); 151 + flexcop_pid_group_filter_ctrl(fc,1); 152 + } 153 + 154 + if (fc->stream_control) 155 + fc->stream_control(fc,1); 156 + flexcop_rcv_data_ctrl(fc,1); 157 + 158 + /* if there is no more feed left to feed */ 159 + } else if (fc->feedcount == onoff && !onoff) { 160 + if (!fc->pid_filtering) { 161 + deb_ts("disabling full TS transfer\n"); 162 + flexcop_pid_group_filter(fc, 0x1fe0,0); 163 + flexcop_pid_group_filter_ctrl(fc,0); 164 + } 165 + 166 + flexcop_rcv_data_ctrl(fc,0); 167 + if (fc->stream_control) 168 + fc->stream_control(fc,0); 169 + } 170 + 171 + /* if pid_filtering is on and more pids than the hw-filter can provide are 172 + * requested enable the whole bandwidth. 173 + */ 174 + if (fc->pid_filtering && fc->feedcount > max_pid_filter) { 175 + flexcop_pid_group_filter(fc, 0,0); 176 + flexcop_pid_group_filter_ctrl(fc,1); 177 + } else if (fc->pid_filtering && fc->feedcount <= max_pid_filter) { 178 + flexcop_pid_group_filter(fc, 0x1fe0,0); 179 + flexcop_pid_group_filter_ctrl(fc,0); 180 + } 181 + 182 + return 0; 183 + } 184 + 185 + void flexcop_hw_filter_init(struct flexcop_device *fc) 186 + { 187 + int i; 188 + flexcop_ibi_value v; 189 + for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++) 190 + flexcop_pid_control(fc,i,0x1fff,0); 191 + 192 + flexcop_pid_group_filter(fc, 0x1fe0,0); 193 + 194 + v = fc->read_ibi_reg(fc,pid_filter_308); 195 + v.pid_filter_308.EMM_filter_4 = 1; 196 + v.pid_filter_308.EMM_filter_6 = 0; 197 + fc->write_ibi_reg(fc,pid_filter_308,v); 198 + }
+204
drivers/media/dvb/b2c2/flexcop-i2c.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + #define FC_MAX_I2C_RETRIES 100000 11 + 12 + static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100, int max_ack_errors) 13 + { 14 + int i,ack_errors = 0; 15 + flexcop_ibi_value r; 16 + 17 + r100->tw_sm_c_100.working_start = 1; 18 + deb_i2c("r100 before: %08x\n",r100->raw); 19 + 20 + fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero); 21 + fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */ 22 + 23 + for (i = 0; i < FC_MAX_I2C_RETRIES; i++) { 24 + r = fc->read_ibi_reg(fc, tw_sm_c_100); 25 + 26 + if (!r.tw_sm_c_100.no_base_addr_ack_error) { 27 + if (r.tw_sm_c_100.st_done) { /* && !r.tw_sm_c_100.working_start */ 28 + *r100 = r; 29 + deb_i2c("i2c success\n"); 30 + return 0; 31 + } 32 + } else { 33 + deb_i2c("suffering from an i2c ack_error\n"); 34 + if (++ack_errors >= max_ack_errors) 35 + break; 36 + 37 + fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero); 38 + fc->write_ibi_reg(fc, tw_sm_c_100, *r100); 39 + } 40 + } 41 + deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i); 42 + return -EREMOTEIO; 43 + } 44 + 45 + static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf) 46 + { 47 + flexcop_ibi_value r104; 48 + int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ 49 + ret; 50 + 51 + if ((ret = flexcop_i2c_operation(fc,&r100,30)) != 0) 52 + return ret; 53 + 54 + r104 = fc->read_ibi_reg(fc,tw_sm_c_104); 55 + 56 + deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw); 57 + 58 + /* there is at least one byte, otherwise we wouldn't be here */ 59 + buf[0] = r100.tw_sm_c_100.data1_reg; 60 + 61 + if (len > 0) buf[1] = r104.tw_sm_c_104.data2_reg; 62 + if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; 63 + if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; 64 + 65 + return 0; 66 + } 67 + 68 + static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf) 69 + { 70 + flexcop_ibi_value r104; 71 + int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */ 72 + r104.raw = 0; 73 + 74 + /* there is at least one byte, otherwise we wouldn't be here */ 75 + r100.tw_sm_c_100.data1_reg = buf[0]; 76 + 77 + r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0; 78 + r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0; 79 + r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0; 80 + 81 + deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw); 82 + 83 + /* write the additional i2c data before doing the actual i2c operation */ 84 + fc->write_ibi_reg(fc,tw_sm_c_104,r104); 85 + 86 + return flexcop_i2c_operation(fc,&r100,30); 87 + } 88 + 89 + /* master xfer callback for demodulator */ 90 + static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) 91 + { 92 + struct flexcop_device *fc = i2c_get_adapdata(i2c_adap); 93 + int i, ret = 0; 94 + 95 + if (down_interruptible(&fc->i2c_sem)) 96 + return -ERESTARTSYS; 97 + 98 + /* reading */ 99 + if (num == 2 && 100 + msgs[0].flags == 0 && 101 + msgs[1].flags == I2C_M_RD && 102 + msgs[0].buf != NULL && 103 + msgs[1].buf != NULL) { 104 + 105 + ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len); 106 + 107 + } else for (i = 0; i < num; i++) { /* writing command */ 108 + if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) { 109 + ret = -EINVAL; 110 + break; 111 + } 112 + 113 + ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1); 114 + } 115 + 116 + if (ret < 0) 117 + err("i2c master_xfer failed"); 118 + else 119 + ret = num; 120 + 121 + up(&fc->i2c_sem); 122 + 123 + return ret; 124 + } 125 + 126 + int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, 127 + flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len) 128 + { 129 + int ret; 130 + u16 bytes_to_transfer; 131 + flexcop_ibi_value r100; 132 + 133 + deb_i2c("op = %d\n",op); 134 + r100.raw = 0; 135 + r100.tw_sm_c_100.chipaddr = chipaddr; 136 + r100.tw_sm_c_100.twoWS_rw = op; 137 + r100.tw_sm_c_100.twoWS_port_reg = port; 138 + 139 + while (len != 0) { 140 + bytes_to_transfer = len > 4 ? 4 : len; 141 + 142 + r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1; 143 + r100.tw_sm_c_100.baseaddr = addr; 144 + 145 + if (op == FC_READ) 146 + ret = flexcop_i2c_read4(fc, r100, buf); 147 + else 148 + ret = flexcop_i2c_write4(fc,r100, buf); 149 + 150 + if (ret < 0) 151 + return ret; 152 + 153 + buf += bytes_to_transfer; 154 + addr += bytes_to_transfer; 155 + len -= bytes_to_transfer; 156 + }; 157 + 158 + return 0; 159 + } 160 + /* exported for PCI i2c */ 161 + EXPORT_SYMBOL(flexcop_i2c_request); 162 + 163 + static u32 flexcop_i2c_func(struct i2c_adapter *adapter) 164 + { 165 + return I2C_FUNC_I2C; 166 + } 167 + 168 + static struct i2c_algorithm flexcop_algo = { 169 + .name = "FlexCop I2C algorithm", 170 + .id = I2C_ALGO_BIT, 171 + .master_xfer = flexcop_master_xfer, 172 + .functionality = flexcop_i2c_func, 173 + }; 174 + 175 + int flexcop_i2c_init(struct flexcop_device *fc) 176 + { 177 + int ret; 178 + 179 + sema_init(&fc->i2c_sem,1); 180 + 181 + memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); 182 + strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE); 183 + 184 + i2c_set_adapdata(&fc->i2c_adap,fc); 185 + 186 + fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL; 187 + fc->i2c_adap.algo = &flexcop_algo; 188 + fc->i2c_adap.algo_data = NULL; 189 + fc->i2c_adap.id = I2C_ALGO_BIT; 190 + 191 + if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0) 192 + return ret; 193 + 194 + fc->init_state |= FC_STATE_I2C_INIT; 195 + return 0; 196 + } 197 + 198 + void flexcop_i2c_exit(struct flexcop_device *fc) 199 + { 200 + if (fc->init_state & FC_STATE_I2C_INIT) 201 + i2c_del_adapter(&fc->i2c_adap); 202 + 203 + fc->init_state &= ~FC_STATE_I2C_INIT; 204 + }
+66
drivers/media/dvb/b2c2/flexcop-misc.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-misc.c - miscellaneous functions. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + void flexcop_determine_revision(struct flexcop_device *fc) 11 + { 12 + flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); 13 + 14 + switch (v.misc_204.Rev_N_sig_revision_hi) { 15 + case 0x2: 16 + deb_info("found a FlexCopII.\n"); 17 + fc->rev = FLEXCOP_II; 18 + break; 19 + case 0x3: 20 + deb_info("found a FlexCopIIb.\n"); 21 + fc->rev = FLEXCOP_IIB; 22 + break; 23 + case 0x0: 24 + deb_info("found a FlexCopIII.\n"); 25 + fc->rev = FLEXCOP_III; 26 + break; 27 + default: 28 + err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",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 the additional 32 hardware pid filter.\n"); 34 + else 35 + deb_info("this FlexCop has only the 6 basic main hardware pid filter.\n"); 36 + /* bus parts have to decide if hw pid filtering is used or not. */ 37 + } 38 + 39 + const char *flexcop_revision_names[] = { 40 + "Unkown chip", 41 + "FlexCopII", 42 + "FlexCopIIb", 43 + "FlexCopIII", 44 + }; 45 + 46 + const char *flexcop_device_names[] = { 47 + "Unkown device", 48 + "AirStar 2 DVB-T", 49 + "AirStar 2 ATSC", 50 + "SkyStar 2 DVB-S", 51 + "SkyStar 2 DVB-S (old version)", 52 + "CableStar 2 DVB-C", 53 + }; 54 + 55 + const char *flexcop_bus_names[] = { 56 + "USB", 57 + "PCI", 58 + }; 59 + 60 + void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const 61 + char *suffix) 62 + { 63 + info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix, 64 + flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type], 65 + flexcop_revision_names[fc->rev],suffix); 66 + }
+365
drivers/media/dvb/b2c2/flexcop-pci.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-pci.c - covers the PCI part including DMA transfers. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + 9 + #define FC_LOG_PREFIX "flexcop-pci" 10 + #include "flexcop-common.h" 11 + 12 + static int enable_pid_filtering = 0; 13 + module_param(enable_pid_filtering, int, 0444); 14 + MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); 15 + 16 + #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG 17 + #define dprintk(level,args...) \ 18 + do { if ((debug & level)) printk(args); } while (0) 19 + #define DEBSTATUS "" 20 + #else 21 + #define dprintk(level,args...) 22 + #define DEBSTATUS " (debugging is not enabled)" 23 + #endif 24 + 25 + #define deb_info(args...) dprintk(0x01,args) 26 + #define deb_reg(args...) dprintk(0x02,args) 27 + #define deb_ts(args...) dprintk(0x04,args) 28 + #define deb_irq(args...) dprintk(0x08,args) 29 + 30 + static int debug = 0; 31 + module_param(debug, int, 0644); 32 + MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); 33 + 34 + #define DRIVER_VERSION "0.1" 35 + #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" 36 + #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>" 37 + 38 + struct flexcop_pci { 39 + struct pci_dev *pdev; 40 + 41 + #define FC_PCI_INIT 0x01 42 + #define FC_PCI_DMA_INIT 0x02 43 + int init_state; 44 + 45 + void __iomem *io_mem; 46 + u32 irq; 47 + /* buffersize (at least for DMA1, need to be % 188 == 0, 48 + * this is logic is required */ 49 + #define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188) 50 + #define FC_DEFAULT_DMA2_BUFSIZE (10 * 188) 51 + struct flexcop_dma dma[2]; 52 + 53 + int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ 54 + u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ 55 + 56 + struct flexcop_device *fc_dev; 57 + }; 58 + 59 + static int lastwreg,lastwval,lastrreg,lastrval; 60 + 61 + static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, flexcop_ibi_register r) 62 + { 63 + struct flexcop_pci *fc_pci = fc->bus_specific; 64 + flexcop_ibi_value v; 65 + v.raw = readl(fc_pci->io_mem + r); 66 + 67 + if (lastrreg != r || lastrval != v.raw) { 68 + lastrreg = r; lastrval = v.raw; 69 + deb_reg("new rd: %3x: %08x\n",r,v.raw); 70 + } 71 + 72 + return v; 73 + } 74 + 75 + static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register r, flexcop_ibi_value v) 76 + { 77 + struct flexcop_pci *fc_pci = fc->bus_specific; 78 + 79 + if (lastwreg != r || lastwval != v.raw) { 80 + lastwreg = r; lastwval = v.raw; 81 + deb_reg("new wr: %3x: %08x\n",r,v.raw); 82 + } 83 + 84 + writel(v.raw, fc_pci->io_mem + r); 85 + return 0; 86 + } 87 + 88 + /* When PID filtering is turned on, we use the timer IRQ, because small amounts 89 + * of data need to be passed to the user space instantly as well. When PID 90 + * filtering is turned off, we use the page-change-IRQ */ 91 + static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs) 92 + { 93 + struct flexcop_pci *fc_pci = dev_id; 94 + struct flexcop_device *fc = fc_pci->fc_dev; 95 + flexcop_ibi_value v = fc->read_ibi_reg(fc,irq_20c); 96 + 97 + deb_irq("irq: %08x cur_addr: %08x (%d), our addrs. 1: %08x 2: %08x; 0x000: " 98 + "%08x, 0x00c: %08x\n",v.raw, 99 + fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2, 100 + fc_pci->active_dma1_addr, 101 + fc_pci->dma[0].dma_addr0,fc_pci->dma[0].dma_addr1, 102 + fc->read_ibi_reg(fc,dma1_000).raw, 103 + fc->read_ibi_reg(fc,dma1_00c).raw); 104 + 105 + if (v.irq_20c.DMA1_IRQ_Status == 1) { 106 + if (fc_pci->active_dma1_addr == 0) 107 + flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188); 108 + else 109 + flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size / 188); 110 + 111 + deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr); 112 + fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr; 113 + } else if (v.irq_20c.DMA1_Timer_Status == 1) { 114 + /* for the timer IRQ we only can use buffer dmx feeding, because we don't have 115 + * complete TS packets when reading from the DMA memory */ 116 + dma_addr_t cur_addr = 117 + fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; 118 + u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; 119 + 120 + /* buffer end was reached, restarted from the beginning 121 + * pass the data from last_cur_pos to the buffer end to the demux 122 + */ 123 + if (cur_pos < fc_pci->last_dma1_cur_pos) { 124 + flexcop_pass_dmx_data(fc_pci->fc_dev, 125 + fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, 126 + (fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos); 127 + fc_pci->last_dma1_cur_pos = 0; 128 + } 129 + 130 + if (cur_pos > fc_pci->last_dma1_cur_pos) { 131 + flexcop_pass_dmx_data(fc_pci->fc_dev, 132 + fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, 133 + cur_pos - fc_pci->last_dma1_cur_pos); 134 + } 135 + 136 + fc_pci->last_dma1_cur_pos = cur_pos; 137 + } 138 + 139 + /* packet count would be ideal for hw filtering, but it isn't working. Either 140 + * the data book is wrong, or I'm unable to read it correctly */ 141 + 142 + /* if (v.irq_20c.DMA1_Size_IRQ_Status == 1) { packet counter */ 143 + 144 + return IRQ_HANDLED; 145 + } 146 + 147 + static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) 148 + { 149 + struct flexcop_pci *fc_pci = fc->bus_specific; 150 + if (onoff) { 151 + flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1); 152 + flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1); 153 + flexcop_dma_config_timer(fc,FC_DMA_1,1); 154 + 155 + if (fc_pci->fc_dev->pid_filtering) { 156 + fc_pci->last_dma1_cur_pos = 0; 157 + flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); 158 + } else { 159 + fc_pci->active_dma1_addr = 0; 160 + flexcop_dma_control_size_irq(fc,FC_DMA_1,1); 161 + } 162 + 163 + /* flexcop_dma_config_packet_count(fc,FC_DMA_1,0xc0); 164 + flexcop_dma_control_packet_irq(fc,FC_DMA_1,1); */ 165 + 166 + deb_irq("irqs enabled\n"); 167 + } else { 168 + if (fc_pci->fc_dev->pid_filtering) 169 + flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); 170 + else 171 + flexcop_dma_control_size_irq(fc,FC_DMA_1,0); 172 + 173 + // flexcop_dma_control_packet_irq(fc,FC_DMA_1,0); 174 + deb_irq("irqs disabled\n"); 175 + } 176 + 177 + return 0; 178 + } 179 + 180 + static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci) 181 + { 182 + int ret; 183 + if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0) 184 + return ret; 185 + 186 + if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) 187 + goto dma1_free; 188 + 189 + flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); 190 + flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); 191 + 192 + fc_pci->init_state |= FC_PCI_DMA_INIT; 193 + goto success; 194 + dma1_free: 195 + flexcop_dma_free(&fc_pci->dma[0]); 196 + 197 + success: 198 + return ret; 199 + } 200 + 201 + static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci) 202 + { 203 + if (fc_pci->init_state & FC_PCI_DMA_INIT) { 204 + flexcop_dma_free(&fc_pci->dma[0]); 205 + flexcop_dma_free(&fc_pci->dma[1]); 206 + } 207 + fc_pci->init_state &= ~FC_PCI_DMA_INIT; 208 + } 209 + 210 + static int flexcop_pci_init(struct flexcop_pci *fc_pci) 211 + { 212 + int ret; 213 + u8 card_rev; 214 + 215 + pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev); 216 + info("card revision %x", card_rev); 217 + 218 + if ((ret = pci_enable_device(fc_pci->pdev)) != 0) 219 + return ret; 220 + 221 + pci_set_master(fc_pci->pdev); 222 + 223 + /* enable interrupts */ 224 + // pci_write_config_dword(pdev, 0x6c, 0x8000); 225 + 226 + if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0) 227 + goto err_pci_disable_device; 228 + 229 + fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800); 230 + 231 + if (!fc_pci->io_mem) { 232 + err("cannot map io memory\n"); 233 + ret = -EIO; 234 + goto err_pci_release_regions; 235 + } 236 + 237 + pci_set_drvdata(fc_pci->pdev, fc_pci); 238 + 239 + if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_irq, 240 + SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0) 241 + goto err_pci_iounmap; 242 + 243 + fc_pci->init_state |= FC_PCI_INIT; 244 + goto success; 245 + 246 + err_pci_iounmap: 247 + pci_iounmap(fc_pci->pdev, fc_pci->io_mem); 248 + pci_set_drvdata(fc_pci->pdev, NULL); 249 + err_pci_release_regions: 250 + pci_release_regions(fc_pci->pdev); 251 + err_pci_disable_device: 252 + pci_disable_device(fc_pci->pdev); 253 + 254 + success: 255 + return ret; 256 + } 257 + 258 + static void flexcop_pci_exit(struct flexcop_pci *fc_pci) 259 + { 260 + if (fc_pci->init_state & FC_PCI_INIT) { 261 + free_irq(fc_pci->pdev->irq, fc_pci); 262 + pci_iounmap(fc_pci->pdev, fc_pci->io_mem); 263 + pci_set_drvdata(fc_pci->pdev, NULL); 264 + pci_release_regions(fc_pci->pdev); 265 + pci_disable_device(fc_pci->pdev); 266 + } 267 + fc_pci->init_state &= ~FC_PCI_INIT; 268 + } 269 + 270 + 271 + static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 272 + { 273 + struct flexcop_device *fc; 274 + struct flexcop_pci *fc_pci; 275 + int ret = -ENOMEM; 276 + 277 + if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_pci))) == NULL) { 278 + err("out of memory\n"); 279 + return -ENOMEM; 280 + } 281 + 282 + /* general flexcop init */ 283 + fc_pci = fc->bus_specific; 284 + fc_pci->fc_dev = fc; 285 + 286 + fc->read_ibi_reg = flexcop_pci_read_ibi_reg; 287 + fc->write_ibi_reg = flexcop_pci_write_ibi_reg; 288 + fc->i2c_request = flexcop_i2c_request; 289 + fc->get_mac_addr = flexcop_eeprom_check_mac_addr; 290 + 291 + fc->stream_control = flexcop_pci_stream_control; 292 + 293 + fc->pid_filtering = enable_pid_filtering; 294 + fc->bus_type = FC_PCI; 295 + 296 + fc->dev = &pdev->dev; 297 + 298 + /* bus specific part */ 299 + fc_pci->pdev = pdev; 300 + if ((ret = flexcop_pci_init(fc_pci)) != 0) 301 + goto err_kfree; 302 + 303 + /* init flexcop */ 304 + if ((ret = flexcop_device_initialize(fc)) != 0) 305 + goto err_pci_exit; 306 + 307 + /* init dma */ 308 + if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) 309 + goto err_fc_exit; 310 + 311 + goto success; 312 + err_fc_exit: 313 + flexcop_device_exit(fc); 314 + err_pci_exit: 315 + flexcop_pci_exit(fc_pci); 316 + err_kfree: 317 + flexcop_device_kfree(fc); 318 + success: 319 + return ret; 320 + } 321 + 322 + /* in theory every _exit function should be called exactly two times, 323 + * here and in the bail-out-part of the _init-function 324 + */ 325 + static void flexcop_pci_remove(struct pci_dev *pdev) 326 + { 327 + struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); 328 + 329 + flexcop_pci_dma_exit(fc_pci); 330 + flexcop_device_exit(fc_pci->fc_dev); 331 + flexcop_pci_exit(fc_pci); 332 + flexcop_device_kfree(fc_pci->fc_dev); 333 + } 334 + 335 + static struct pci_device_id flexcop_pci_tbl[] = { 336 + { PCI_DEVICE(0x13d0, 0x2103) }, 337 + /* { PCI_DEVICE(0x13d0, 0x2200) }, PCI FlexCopIII ? */ 338 + { }, 339 + }; 340 + 341 + MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl); 342 + 343 + static struct pci_driver flexcop_pci_driver = { 344 + .name = "Technisat/B2C2 FlexCop II/IIb/III PCI", 345 + .id_table = flexcop_pci_tbl, 346 + .probe = flexcop_pci_probe, 347 + .remove = flexcop_pci_remove, 348 + }; 349 + 350 + static int __init flexcop_pci_module_init(void) 351 + { 352 + return pci_register_driver(&flexcop_pci_driver); 353 + } 354 + 355 + static void __exit flexcop_pci_module_exit(void) 356 + { 357 + pci_unregister_driver(&flexcop_pci_driver); 358 + } 359 + 360 + module_init(flexcop_pci_module_init); 361 + module_exit(flexcop_pci_module_exit); 362 + 363 + MODULE_AUTHOR(DRIVER_AUTHOR); 364 + MODULE_DESCRIPTION(DRIVER_NAME); 365 + MODULE_LICENSE("GPL");
+700
drivers/media/dvb/b2c2/flexcop-reg.h
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #ifndef __FLEXCOP_REG_H__ 9 + #define __FLEXCOP_REG_H__ 10 + 11 + 12 + typedef enum { 13 + FLEXCOP_UNK = 0, 14 + FLEXCOP_II, 15 + FLEXCOP_IIB, 16 + FLEXCOP_III, 17 + } flexcop_revision_t; 18 + 19 + extern const char *flexcop_revision_names[]; 20 + 21 + typedef enum { 22 + FC_UNK = 0, 23 + FC_AIR_DVB, 24 + FC_AIR_ATSC, 25 + FC_SKY, 26 + FC_SKY_OLD, 27 + FC_CABLE, 28 + } flexcop_device_type_t; 29 + 30 + typedef enum { 31 + FC_USB = 0, 32 + FC_PCI, 33 + } flexcop_bus_t; 34 + 35 + extern const char *flexcop_device_names[]; 36 + 37 + /* FlexCop IBI Registers */ 38 + 39 + /* flexcop_ibi_reg - a huge union representing the register structure */ 40 + typedef union { 41 + u32 raw; 42 + 43 + /* DMA 0x000 to 0x01c 44 + * DMA1 0x000 to 0x00c 45 + * DMA2 0x010 to 0x01c 46 + */ 47 + struct { 48 + u32 dma_0start : 1; /* set: data will be delivered to dma1_address0 */ 49 + u32 dma_0No_update : 1; /* set: dma1_cur_address will be updated, unset: no update */ 50 + u32 dma_address0 :30; /* physical/virtual host memory address0 DMA */ 51 + } dma_0x0; 52 + 53 + struct { 54 + u32 DMA_maxpackets : 8; /* (remapped) PCI DMA1 Packet Count Interrupt. This variable 55 + is able to be read and written while bit(1) of register 56 + 0x00c (remap_enable) is set. This variable represents 57 + the number of packets that will be transmitted to the PCI 58 + host using PCI DMA1 before an interrupt to the PCI is 59 + asserted. This functionality may be enabled using bit(20) 60 + of register 0x208. N=0 disables the IRQ. */ 61 + u32 dma_addr_size :24; /* size of memory buffer in DWORDs (bytesize / 4) for DMA */ 62 + } dma_0x4_remap; 63 + 64 + struct { 65 + u32 dma1timer : 7; /* reading PCI DMA1 timer ... when remap_enable is 0 */ 66 + u32 unused : 1; 67 + u32 dma_addr_size :24; 68 + } dma_0x4_read; 69 + 70 + struct { 71 + u32 unused : 1; 72 + u32 dmatimer : 7; /* writing PCI DMA1 timer ... when remap_enable is 0 */ 73 + u32 dma_addr_size :24; 74 + } dma_0x4_write; 75 + 76 + struct { 77 + u32 unused : 2; 78 + u32 dma_cur_addr :30; /* current physical host memory address pointer for DMA */ 79 + } dma_0x8; 80 + 81 + struct { 82 + u32 dma_1start : 1; /* set: data will be delivered to dma_address1, when dma_address0 is full */ 83 + u32 remap_enable : 1; /* remap enable for 0x0x4(7:0) */ 84 + u32 dma_address1 :30; /* Physical/virtual address 1 on DMA */ 85 + } dma_0xc; 86 + 87 + /* Two-wire Serial Master and Clock 0x100-0x110 */ 88 + struct { 89 + // u32 slave_transmitter : 1; /* ???*/ 90 + u32 chipaddr : 7; /* two-line serial address of the target slave */ 91 + u32 reserved1 : 1; 92 + u32 baseaddr : 8; /* address of the location of the read/write operation */ 93 + u32 data1_reg : 8; /* first byte in two-line serial read/write operation */ 94 + u32 working_start : 1; /* when doing a write operation this indicator is 0 when ready 95 + * set to 1 when doing a write operation */ 96 + u32 twoWS_rw : 1; /* read/write indicator (1 = read, 0 write) */ 97 + u32 total_bytes : 2; /* number of data bytes in each two-line serial transaction (0 = 1 byte, 11 = 4byte)*/ 98 + u32 twoWS_port_reg : 2; /* port selection: 01 - Front End/Demod, 10 - EEPROM, 11 - Tuner */ 99 + u32 no_base_addr_ack_error : 1; /* writing: write-req: frame is produced w/o baseaddr, read-req: read-cycles w/o 100 + * preceding address assignment write frame 101 + * ACK_ERROR = 1 when no ACK from slave in the last transaction */ 102 + u32 st_done : 1; /* indicator for transaction is done */ 103 + } tw_sm_c_100; 104 + 105 + struct { 106 + u32 data2_reg : 8; /* 2nd data byte */ 107 + u32 data3_reg : 8; /* 3rd data byte */ 108 + u32 data4_reg : 8; /* 4th data byte */ 109 + u32 exlicit_stops : 1; /* when set, transactions are produced w/o trailing STOP flag, then send isolated STOP flags */ 110 + u32 force_stop : 1; /* isolated stop flag */ 111 + u32 unused : 6; 112 + } tw_sm_c_104; 113 + 114 + /* Clock. The register allows the FCIII to convert an incoming Master clock 115 + * (MCLK) signal into a lower frequency clock through the use of a LowCounter 116 + * (TLO) and a High- Counter (THI). The time counts for THI and TLO are 117 + * measured in MCLK; each count represents 4 MCLK input clock cycles. 118 + * 119 + * The default output for port #1 is set for Front End Demod communication. (0x108) 120 + * The default output for port #2 is set for EEPROM communication. (0x10c) 121 + * The default output for port #3 is set for Tuner communication. (0x110) 122 + */ 123 + struct { 124 + u32 thi1 : 6; /* Thi for port #1 (def: 100110b; 38) */ 125 + u32 reserved1 : 2; 126 + u32 tlo1 : 5; /* Tlo for port #1 (def: 11100b; 28) */ 127 + u32 reserved2 :19; 128 + } tw_sm_c_108; 129 + 130 + struct { 131 + u32 thi1 : 6; /* Thi for port #2 (def: 111001b; 57) */ 132 + u32 reserved1 : 2; 133 + u32 tlo1 : 5; /* Tlo for port #2 (def: 11100b; 28) */ 134 + u32 reserved2 :19; 135 + } tw_sm_c_10c; 136 + 137 + struct { 138 + u32 thi1 : 6; /* Thi for port #3 (def: 111001b; 57) */ 139 + u32 reserved1 : 2; 140 + u32 tlo1 : 5; /* Tlo for port #3 (def: 11100b; 28) */ 141 + u32 reserved2 :19; 142 + } tw_sm_c_110; 143 + 144 + /* LNB Switch Frequency 0x200 145 + * Clock that creates the LNB switch tone. The default is set to have a fixed 146 + * low output (not oscillating) to the LNB_CTL line. 147 + */ 148 + struct { 149 + u32 LNB_CTLHighCount_sig :15; /* It is the number of pre-scaled clock cycles that will be low. */ 150 + u32 LNB_CTLLowCount_sig :15; /* For example, to obtain a 22KHz output given a 45 Mhz Master 151 + Clock signal (MCLK), set PreScalar=01 and LowCounter value to 0x1ff. */ 152 + u32 LNB_CTLPrescaler_sig : 2; /* pre-scaler divides MCLK: 00 (no division), 01 by 2, 10 by 4, 11 by 12 */ 153 + } lnb_switch_freq_200; 154 + 155 + /* ACPI, Peripheral Reset, LNB Polarity 156 + * ACPI power conservation mode, LNB polarity selection (low or high voltage), 157 + * and peripheral reset. 158 + */ 159 + struct { 160 + u32 ACPI1_sig : 1; /* turn of the power of tuner and LNB, not implemented in FCIII */ 161 + u32 ACPI3_sig : 1; /* turn of power of the complete satelite receiver board (except FCIII) */ 162 + u32 LNB_L_H_sig : 1; /* low or high voltage for LNB. (0 = low, 1 = high) */ 163 + u32 Per_reset_sig : 1; /* misc. init reset (default: 1), to reset set to low and back to high */ 164 + u32 reserved :20; 165 + u32 Rev_N_sig_revision_hi : 4;/* 0xc in case of FCIII */ 166 + u32 Rev_N_sig_reserved1 : 2; 167 + u32 Rev_N_sig_caps : 1; /* if 1, FCIII has 32 PID- and MAC-filters and is capable of IP multicast */ 168 + u32 Rev_N_sig_reserved2 : 1; 169 + } misc_204; 170 + 171 + /* Control and Status 0x208 to 0x21c */ 172 + /* Gross enable and disable control */ 173 + struct { 174 + u32 Stream1_filter_sig : 1; /* Stream1 PID filtering */ 175 + u32 Stream2_filter_sig : 1; /* Stream2 PID filtering */ 176 + u32 PCR_filter_sig : 1; /* PCR PID filter */ 177 + u32 PMT_filter_sig : 1; /* PMT PID filter */ 178 + 179 + u32 EMM_filter_sig : 1; /* EMM PID filter */ 180 + u32 ECM_filter_sig : 1; /* ECM PID filter */ 181 + u32 Null_filter_sig : 1; /* Filters null packets, PID=0x1fff. */ 182 + u32 Mask_filter_sig : 1; /* mask PID filter */ 183 + 184 + u32 WAN_Enable_sig : 1; /* WAN output line through V8 memory space is activated. */ 185 + u32 WAN_CA_Enable_sig : 1; /* not in FCIII */ 186 + u32 CA_Enable_sig : 1; /* not in FCIII */ 187 + u32 SMC_Enable_sig : 1; /* CI stream data (CAI) goes directly to the smart card intf (opposed IBI 0x600 or SC-cmd buf). */ 188 + 189 + u32 Per_CA_Enable_sig : 1; /* not in FCIII */ 190 + u32 Multi2_Enable_sig : 1; /* ? */ 191 + u32 MAC_filter_Mode_sig : 1; /* (MAC_filter_enable) Globally enables MAC filters for Net PID filteres. */ 192 + u32 Rcv_Data_sig : 1; /* PID filtering module enable. When this bit is a one, the PID filter will 193 + examine and process packets according to all other (individual) PID 194 + filtering controls. If it a zero, no packet processing of any kind will 195 + take place. All data from the tuner will be thrown away. */ 196 + 197 + u32 DMA1_IRQ_Enable_sig : 1; /* When set, a DWORD counter is enabled on PCI DMA1 that asserts the PCI 198 + * interrupt after the specified count for filling the buffer. */ 199 + u32 DMA1_Timer_Enable_sig : 1; /* When set, a timer is enabled on PCI DMA1 that asserts the PCI interrupt 200 + after a specified amount of time. */ 201 + u32 DMA2_IRQ_Enable_sig : 1; /* same as DMA1_IRQ_Enable_sig but for DMA2 */ 202 + u32 DMA2_Timer_Enable_sig : 1; /* same as DMA1_Timer_Enable_sig but for DMA2 */ 203 + 204 + u32 DMA1_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA1 that asserts the PCI interrupt. */ 205 + u32 DMA2_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA2 that asserts the PCI interrupt. */ 206 + u32 Mailbox_from_V8_Enable_sig: 1; /* When set, writes to the mailbox register produce an interrupt to the 207 + PCI host to indicate that mailbox data is available. */ 208 + 209 + u32 unused : 9; 210 + } ctrl_208; 211 + 212 + /* General status. When a PCI interrupt occurs, this register is read to 213 + * discover the reason for the interrupt. 214 + */ 215 + struct { 216 + u32 DMA1_IRQ_Status : 1; /* When set(1) the DMA1 counter had generated an IRQ. Read Only. */ 217 + u32 DMA1_Timer_Status : 1; /* When set(1) the DMA1 timer had generated an IRQ. Read Only. */ 218 + u32 DMA2_IRQ_Status : 1; /* When set(1) the DMA2 counter had generated an IRQ. Read Only. */ 219 + u32 DMA2_Timer_Status : 1; /* When set(1) the DMA2 timer had generated an IRQ. Read Only. */ 220 + u32 DMA1_Size_IRQ_Status : 1; /* (Read only). This register is read after an interrupt to */ 221 + u32 DMA2_Size_IRQ_Status : 1; /* find out why we had an IRQ. Reading this register will clear this bit. Packet count*/ 222 + u32 Mailbox_from_V8_Status_sig: 1; /* Same as above. Reading this register will clear this bit. */ 223 + u32 Data_receiver_error : 1; /* 1 indicate an error in the receiver Front End (Tuner module) */ 224 + u32 Continuity_error_flag : 1; /* 1 indicates a continuity error in the TS stream. */ 225 + u32 LLC_SNAP_FLAG_set : 1; /* 1 indicates that the LCC_SNAP_FLAG was set. */ 226 + u32 Transport_Error : 1; /* When set indicates that an unexpected packet was received. */ 227 + u32 reserved :21; 228 + } irq_20c; 229 + 230 + 231 + /* Software reset register */ 232 + struct { 233 + u32 reset_blocks : 8; /* Enabled when Block_reset_enable = 0xB2 and 0x208 bits 15:8 = 0x00. 234 + Each bit location represents a 0x100 block of registers. Writing 235 + a one in a bit location resets that block of registers and the logic 236 + that it controls. */ 237 + u32 Block_reset_enable : 8; /* This variable is set to 0xB2 when the register is written. */ 238 + u32 Special_controls :16; /* Asserts Reset_V8 => 0xC258; Turns on pci encryption => 0xC25A; 239 + Turns off pci encryption => 0xC259 Note: pci_encryption default 240 + at power-up is ON. */ 241 + } sw_reset_210; 242 + 243 + struct { 244 + u32 vuart_oe_sig : 1; /* When clear, the V8 processor has sole control of the serial UART 245 + (RS-232 Smart Card interface). When set, the IBI interface 246 + defined by register 0x600 controls the serial UART. */ 247 + u32 v2WS_oe_sig : 1; /* When clear, the V8 processor has direct control of the Two-line 248 + Serial Master EEPROM target. When set, the Two-line Serial Master 249 + EEPROM target interface is controlled by IBI register 0x100. */ 250 + u32 halt_V8_sig : 1; /* When set, contiguous wait states are applied to the V8-space 251 + bus masters. Once this signal is cleared, normal V8-space 252 + operations resume. */ 253 + u32 section_pkg_enable_sig: 1; /* When set, this signal enables the front end translation circuitry 254 + to process section packed transport streams. */ 255 + u32 s2p_sel_sig : 1; /* Serial to parallel conversion. When set, polarized transport data 256 + within the FlexCop3 front end circuitry is converted from a serial 257 + stream into parallel data before downstream processing otherwise 258 + interprets the data. */ 259 + u32 unused1 : 3; 260 + u32 polarity_PS_CLK_sig: 1; /* This signal is used to invert the input polarity of the tranport 261 + stream CLOCK signal before any processing occurs on the transport 262 + stream within FlexCop3. */ 263 + u32 polarity_PS_VALID_sig: 1; /* This signal is used to invert the input polarity of the tranport 264 + stream VALID signal before any processing occurs on the transport 265 + stream within FlexCop3. */ 266 + u32 polarity_PS_SYNC_sig: 1; /* This signal is used to invert the input polarity of the tranport 267 + stream SYNC signal before any processing occurs on the transport 268 + stream within FlexCop3. */ 269 + u32 polarity_PS_ERR_sig: 1; /* This signal is used to invert the input polarity of the tranport 270 + stream ERROR signal before any processing occurs on the transport 271 + stream within FlexCop3. */ 272 + u32 unused2 :20; 273 + } misc_214; 274 + 275 + /* Mailbox from V8 to host */ 276 + struct { 277 + u32 Mailbox_from_V8 :32; /* When this register is written by either the V8 processor or by an 278 + end host, an interrupt is generated to the PCI host to indicate 279 + that mailbox data is available. Reading register 20c will clear 280 + the IRQ. */ 281 + } mbox_v8_to_host_218; 282 + 283 + /* Mailbox from host to v8 Mailbox_to_V8 284 + * Mailbox_to_V8 mailbox storage register 285 + * used to send messages from PCI to V8. Writing to this register will send an 286 + * IRQ to the V8. Then it can read the data from here. Reading this register 287 + * will clear the IRQ. If the V8 is halted and bit 31 of this register is set, 288 + * then this register is used instead as a direct interface to access the 289 + * V8space memory. 290 + */ 291 + struct { 292 + u32 sysramaccess_data : 8; /* Data byte written or read from the specified address in V8 SysRAM. */ 293 + u32 sysramaccess_addr :15; /* 15 bit address used to access V8 Sys-RAM. */ 294 + u32 unused : 7; 295 + u32 sysramaccess_write: 1; /* Write flag used to latch data into the V8 SysRAM. */ 296 + u32 sysramaccess_busmuster: 1; /* Setting this bit when the V8 is halted at 0x214 Bit(2) allows 297 + this IBI register interface to directly drive the V8-space memory. */ 298 + } mbox_host_to_v8_21c; 299 + 300 + 301 + /* PIDs, Translation Bit, SMC Filter Select 0x300 to 0x31c */ 302 + struct { 303 + u32 Stream1_PID :13; /* Primary use is receiving Net data, so these 13 bits normally 304 + hold the PID value for the desired network stream. */ 305 + u32 Stream1_trans : 1; /* When set, Net translation will take place for Net data ferried in TS packets. */ 306 + u32 MAC_Multicast_filter : 1; /* When clear, multicast MAC filtering is not allowed for Stream1 and PID_n filters. */ 307 + u32 debug_flag_pid_saved : 1; 308 + u32 Stream2_PID :13; /* 13 bits for Stream 2 PID filter value. General use. */ 309 + u32 Stream2_trans : 1; /* When set Tables/CAI translation will take place for the data ferried in 310 + Stream2_PID TS packets. */ 311 + u32 debug_flag_write_status00 : 1; 312 + u32 debug_fifo_problem : 1; 313 + } pid_filter_300; 314 + 315 + struct { 316 + u32 PCR_PID :13; /* PCR stream PID filter value. Primary use is Program Clock Reference stream filtering. */ 317 + u32 PCR_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */ 318 + u32 debug_overrun3 : 1; 319 + u32 debug_overrun2 : 1; 320 + u32 PMT_PID :13; /* stream PID filter value. Primary use is Program Management Table segment filtering. */ 321 + u32 PMT_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */ 322 + u32 reserved : 2; 323 + } pid_filter_304; 324 + 325 + struct { 326 + u32 EMM_PID :13; /* EMM PID filter value. Primary use is Entitlement Management Messaging for 327 + conditional access-related data. */ 328 + u32 EMM_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */ 329 + u32 EMM_filter_4 : 1; /* When set will pass only EMM data possessing the same ID code as the 330 + first four bytes (32 bits) of the end-user s 6-byte Smart Card ID number Select */ 331 + u32 EMM_filter_6 : 1; /* When set will pass only EMM data possessing the same 6-byte code as the end-users 332 + complete 6-byte Smart Card ID number. */ 333 + u32 ECM_PID :13; /* ECM PID filter value. Primary use is Entitlement Control Messaging for conditional 334 + access-related data. */ 335 + u32 ECM_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */ 336 + u32 reserved : 2; 337 + } pid_filter_308; 338 + 339 + struct { 340 + u32 Group_PID :13; /* PID value for group filtering. */ 341 + u32 Group_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */ 342 + u32 unused1 : 2; 343 + u32 Group_mask :13; /* Mask value used in logical "and" equation that defines group filtering */ 344 + u32 unused2 : 3; 345 + } pid_filter_30c_ext_ind_0_7; 346 + 347 + struct { 348 + u32 net_master_read :17; 349 + u32 unused :15; 350 + } pid_filter_30c_ext_ind_1; 351 + 352 + struct { 353 + u32 net_master_write :17; 354 + u32 unused :15; 355 + } pid_filter_30c_ext_ind_2; 356 + 357 + struct { 358 + u32 next_net_master_write :17; 359 + u32 unused :15; 360 + } pid_filter_30c_ext_ind_3; 361 + 362 + struct { 363 + u32 unused1 : 1; 364 + u32 state_write :10; 365 + u32 reserved1 : 6; /* default: 000100 */ 366 + u32 stack_read :10; 367 + u32 reserved2 : 5; /* default: 00100 */ 368 + } pid_filter_30c_ext_ind_4; 369 + 370 + struct { 371 + u32 stack_cnt :10; 372 + u32 unused :22; 373 + } pid_filter_30c_ext_ind_5; 374 + 375 + struct { 376 + u32 pid_fsm_save_reg0 : 2; 377 + u32 pid_fsm_save_reg1 : 2; 378 + u32 pid_fsm_save_reg2 : 2; 379 + u32 pid_fsm_save_reg3 : 2; 380 + u32 pid_fsm_save_reg4 : 2; 381 + u32 pid_fsm_save_reg300 : 2; 382 + u32 write_status1 : 2; 383 + u32 write_status4 : 2; 384 + u32 data_size_reg :12; 385 + u32 unused : 4; 386 + } pid_filter_30c_ext_ind_6; 387 + 388 + struct { 389 + u32 index_reg : 5; /* (Index pointer) Points at an internal PIDn register. A binary code 390 + representing one of 32 internal PIDn registers as well as its 391 + corresponding internal MAC_lown register. */ 392 + u32 extra_index_reg : 3; /* This vector is used to select between sets of debug signals routed to register 0x30c. */ 393 + u32 AB_select : 1; /* Used in conjunction with 0x31c. read/write to the MAC_highA or MAC_highB register 394 + 0=MAC_highB register, 1=MAC_highA */ 395 + u32 pass_alltables : 1; /* 1=Net packets are not filtered against the Network Table ID found in register 0x400. 396 + All types of networks (DVB, ATSC, ISDB) are passed. */ 397 + u32 unused :22; 398 + } index_reg_310; 399 + 400 + struct { 401 + u32 PID :13; /* PID value */ 402 + u32 PID_trans : 1; /* translation will take place for packets filtered */ 403 + u32 PID_enable_bit : 1; /* When set this PID filter is enabled */ 404 + u32 reserved :17; 405 + } pid_n_reg_314; 406 + 407 + struct { 408 + u32 A4_byte : 8; 409 + u32 A5_byte : 8; 410 + u32 A6_byte : 8; 411 + u32 Enable_bit : 1; /* enabled (1) or disabled (1) */ 412 + u32 HighAB_bit : 1; /* use MAC_highA (1) or MAC_highB (0) as MSB */ 413 + u32 reserved : 6; 414 + } mac_low_reg_318; 415 + 416 + struct { 417 + u32 A1_byte : 8; 418 + u32 A2_byte : 8; 419 + u32 A3_byte : 8; 420 + u32 reserved : 8; 421 + } mac_high_reg_31c; 422 + 423 + /* Table, SMCID,MACDestination Filters 0x400 to 0x41c */ 424 + struct { 425 + u32 reserved :16; 426 + #define fc_data_Tag_ID_DVB 0x3e 427 + #define fc_data_Tag_ID_ATSC 0x3f 428 + #define fc_data_Tag_ID_IDSB 0x8b 429 + u32 data_Tag_ID :16; 430 + } data_tag_400; 431 + 432 + struct { 433 + u32 Card_IDbyte6 : 8; 434 + u32 Card_IDbyte5 : 8; 435 + u32 Card_IDbyte4 : 8; 436 + u32 Card_IDbyte3 : 8; 437 + } card_id_408; 438 + 439 + struct { 440 + u32 Card_IDbyte2 : 8; 441 + u32 Card_IDbyte1 : 8; 442 + } card_id_40c; 443 + 444 + /* holding the unique mac address of the receiver which houses the FlexCopIII */ 445 + struct { 446 + u32 MAC1 : 8; 447 + u32 MAC2 : 8; 448 + u32 MAC3 : 8; 449 + u32 MAC6 : 8; 450 + } mac_address_418; 451 + 452 + struct { 453 + u32 MAC7 : 8; 454 + u32 MAC8 : 8; 455 + u32 reserved : 16; 456 + } mac_address_41c; 457 + 458 + struct { 459 + u32 transmitter_data_byte : 8; 460 + u32 ReceiveDataReady : 1; 461 + u32 ReceiveByteFrameError: 1; 462 + u32 txbuffempty : 1; 463 + u32 reserved :21; 464 + } ci_600; 465 + 466 + struct { 467 + u32 pi_d : 8; 468 + u32 pi_ha :20; 469 + u32 pi_rw : 1; 470 + u32 pi_component_reg : 3; 471 + } pi_604; 472 + 473 + struct { 474 + u32 serialReset : 1; 475 + u32 oncecycle_read : 1; 476 + u32 Timer_Read_req : 1; 477 + u32 Timer_Load_req : 1; 478 + u32 timer_data : 7; 479 + u32 unused : 1; /* ??? not mentioned in data book */ 480 + u32 Timer_addr : 5; 481 + u32 reserved : 3; 482 + u32 pcmcia_a_mod_pwr_n : 1; 483 + u32 pcmcia_b_mod_pwr_n : 1; 484 + u32 config_Done_stat : 1; 485 + u32 config_Init_stat : 1; 486 + u32 config_Prog_n : 1; 487 + u32 config_wr_n : 1; 488 + u32 config_cs_n : 1; 489 + u32 config_cclk : 1; 490 + u32 pi_CiMax_IRQ_n : 1; 491 + u32 pi_timeout_status : 1; 492 + u32 pi_wait_n : 1; 493 + u32 pi_busy_n : 1; 494 + } pi_608; 495 + 496 + struct { 497 + u32 PID :13; 498 + u32 key_enable : 1; 499 + #define fc_key_code_default 0x1 500 + #define fc_key_code_even 0x2 501 + #define fc_key_code_odd 0x3 502 + u32 key_code : 2; 503 + u32 key_array_col : 3; 504 + u32 key_array_row : 5; 505 + u32 dvb_en : 1; /* 0=TS bypasses the Descrambler */ 506 + u32 rw_flag : 1; 507 + u32 reserved : 6; 508 + } dvb_reg_60c; 509 + 510 + /* SRAM and Output Destination 0x700 to 0x714 */ 511 + struct { 512 + u32 sram_addr :15; 513 + u32 sram_rw : 1; /* 0=write, 1=read */ 514 + u32 sram_data : 8; 515 + u32 sc_xfer_bit : 1; 516 + u32 reserved1 : 3; 517 + u32 oe_pin_reg : 1; 518 + u32 ce_pin_reg : 1; 519 + u32 reserved2 : 1; 520 + u32 start_sram_ibi : 1; 521 + } sram_ctrl_reg_700; 522 + 523 + struct { 524 + u32 net_addr_read :16; 525 + u32 net_addr_write :16; 526 + } net_buf_reg_704; 527 + 528 + struct { 529 + u32 cai_read :11; 530 + u32 reserved1 : 5; 531 + u32 cai_write :11; 532 + u32 reserved2 : 6; 533 + u32 cai_cnt : 4; 534 + } cai_buf_reg_708; 535 + 536 + struct { 537 + u32 cao_read :11; 538 + u32 reserved1 : 5; 539 + u32 cap_write :11; 540 + u32 reserved2 : 6; 541 + u32 cao_cnt : 4; 542 + } cao_buf_reg_70c; 543 + 544 + struct { 545 + u32 media_read :11; 546 + u32 reserved1 : 5; 547 + u32 media_write :11; 548 + u32 reserved2 : 6; 549 + u32 media_cnt : 4; 550 + } media_buf_reg_710; 551 + 552 + struct { 553 + u32 NET_Dest : 2; 554 + u32 CAI_Dest : 2; 555 + u32 CAO_Dest : 2; 556 + u32 MEDIA_Dest : 2; 557 + u32 net_ovflow_error : 1; 558 + u32 media_ovflow_error : 1; 559 + u32 cai_ovflow_error : 1; 560 + u32 cao_ovflow_error : 1; 561 + u32 ctrl_usb_wan : 1; 562 + u32 ctrl_sramdma : 1; 563 + u32 ctrl_maximumfill : 1; 564 + u32 reserved :17; 565 + } sram_dest_reg_714; 566 + 567 + struct { 568 + u32 net_cnt :12; 569 + u32 reserved1 : 4; 570 + u32 net_addr_read : 1; 571 + u32 reserved2 : 3; 572 + u32 net_addr_write : 1; 573 + u32 reserved3 :11; 574 + } net_buf_reg_718; 575 + 576 + struct { 577 + u32 wan_speed_sig : 2; 578 + u32 reserved1 : 6; 579 + u32 wan_wait_state : 8; 580 + u32 sram_chip : 2; 581 + u32 sram_memmap : 2; 582 + u32 reserved2 : 4; 583 + u32 wan_pkt_frame : 4; 584 + u32 reserved3 : 4; 585 + } wan_ctrl_reg_71c; 586 + } flexcop_ibi_value; 587 + 588 + extern flexcop_ibi_value ibi_zero; 589 + 590 + typedef enum { 591 + FC_I2C_PORT_DEMOD = 1, 592 + FC_I2C_PORT_EEPROM = 2, 593 + FC_I2C_PORT_TUNER = 3, 594 + } flexcop_i2c_port_t; 595 + 596 + typedef enum { 597 + FC_WRITE = 0, 598 + FC_READ = 1, 599 + } flexcop_access_op_t; 600 + 601 + typedef enum { 602 + FC_SRAM_DEST_NET = 1, 603 + FC_SRAM_DEST_CAI = 2, 604 + FC_SRAM_DEST_CAO = 4, 605 + FC_SRAM_DEST_MEDIA = 8 606 + } flexcop_sram_dest_t; 607 + 608 + typedef enum { 609 + FC_SRAM_DEST_TARGET_WAN_USB = 0, 610 + FC_SRAM_DEST_TARGET_DMA1 = 1, 611 + FC_SRAM_DEST_TARGET_DMA2 = 2, 612 + FC_SRAM_DEST_TARGET_FC3_CA = 3 613 + } flexcop_sram_dest_target_t; 614 + 615 + typedef enum { 616 + FC_SRAM_2_32KB = 0, /* 64KB */ 617 + FC_SRAM_1_32KB = 1, /* 32KB - default fow FCII */ 618 + FC_SRAM_1_128KB = 2, /* 128KB */ 619 + FC_SRAM_1_48KB = 3, /* 48KB - default for FCIII */ 620 + } flexcop_sram_type_t; 621 + 622 + typedef enum { 623 + FC_WAN_SPEED_4MBITS = 0, 624 + FC_WAN_SPEED_8MBITS = 1, 625 + FC_WAN_SPEED_12MBITS = 2, 626 + FC_WAN_SPEED_16MBITS = 3, 627 + } flexcop_wan_speed_t; 628 + 629 + typedef enum { 630 + FC_DMA_1 = 1, 631 + FC_DMA_2 = 2, 632 + } flexcop_dma_index_t; 633 + 634 + typedef enum { 635 + FC_DMA_SUBADDR_0 = 1, 636 + FC_DMA_SUBADDR_1 = 2, 637 + } flexcop_dma_addr_index_t; 638 + 639 + /* names of the particular registers */ 640 + typedef enum { 641 + dma1_000 = 0x000, 642 + dma1_004 = 0x004, 643 + dma1_008 = 0x008, 644 + dma1_00c = 0x00c, 645 + dma2_010 = 0x010, 646 + dma2_014 = 0x014, 647 + dma2_018 = 0x018, 648 + dma2_01c = 0x01c, 649 + 650 + tw_sm_c_100 = 0x100, 651 + tw_sm_c_104 = 0x104, 652 + tw_sm_c_108 = 0x108, 653 + tw_sm_c_10c = 0x10c, 654 + tw_sm_c_110 = 0x110, 655 + 656 + lnb_switch_freq_200 = 0x200, 657 + misc_204 = 0x204, 658 + ctrl_208 = 0x208, 659 + irq_20c = 0x20c, 660 + sw_reset_210 = 0x210, 661 + misc_214 = 0x214, 662 + mbox_v8_to_host_218 = 0x218, 663 + mbox_host_to_v8_21c = 0x21c, 664 + 665 + pid_filter_300 = 0x300, 666 + pid_filter_304 = 0x304, 667 + pid_filter_308 = 0x308, 668 + pid_filter_30c = 0x30c, 669 + index_reg_310 = 0x310, 670 + pid_n_reg_314 = 0x314, 671 + mac_low_reg_318 = 0x318, 672 + mac_high_reg_31c = 0x31c, 673 + 674 + data_tag_400 = 0x400, 675 + card_id_408 = 0x408, 676 + card_id_40c = 0x40c, 677 + mac_address_418 = 0x418, 678 + mac_address_41c = 0x41c, 679 + 680 + ci_600 = 0x600, 681 + pi_604 = 0x604, 682 + pi_608 = 0x608, 683 + dvb_reg_60c = 0x60c, 684 + 685 + sram_ctrl_reg_700 = 0x700, 686 + net_buf_reg_704 = 0x704, 687 + cai_buf_reg_708 = 0x708, 688 + cao_buf_reg_70c = 0x70c, 689 + media_buf_reg_710 = 0x710, 690 + sram_dest_reg_714 = 0x714, 691 + net_buf_reg_718 = 0x718, 692 + wan_ctrl_reg_71c = 0x71c, 693 + } flexcop_ibi_register; 694 + 695 + #define flexcop_set_ibi_value(reg,attr,val) \ 696 + flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \ 697 + v.reg.attr = val; \ 698 + fc->write_ibi_reg(fc,reg,v); \ 699 + 700 + #endif
+403
drivers/media/dvb/b2c2/flexcop-sram.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-sram.c - functions for controlling the SRAM. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #include "flexcop.h" 9 + 10 + static void flexcop_sram_set_chip (struct flexcop_device *fc, flexcop_sram_type_t type) 11 + { 12 + flexcop_set_ibi_value(wan_ctrl_reg_71c,sram_chip,type); 13 + } 14 + 15 + int flexcop_sram_init(struct flexcop_device *fc) 16 + { 17 + switch (fc->rev) { 18 + case FLEXCOP_II: 19 + case FLEXCOP_IIB: 20 + flexcop_sram_set_chip(fc,FC_SRAM_1_32KB); 21 + break; 22 + case FLEXCOP_III: 23 + flexcop_sram_set_chip(fc,FC_SRAM_1_48KB); 24 + break; 25 + default: 26 + return -EINVAL; 27 + } 28 + return 0; 29 + } 30 + 31 + int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target) 32 + { 33 + flexcop_ibi_value v; 34 + 35 + v = fc->read_ibi_reg(fc,sram_dest_reg_714); 36 + 37 + if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) { 38 + err("SRAM destination target to available on FlexCopII(b)\n"); 39 + return -EINVAL; 40 + } 41 + 42 + deb_sram("sram dest: %x target: %x\n",dest, target); 43 + 44 + if (dest & FC_SRAM_DEST_NET) 45 + v.sram_dest_reg_714.NET_Dest = target; 46 + if (dest & FC_SRAM_DEST_CAI) 47 + v.sram_dest_reg_714.CAI_Dest = target; 48 + if (dest & FC_SRAM_DEST_CAO) 49 + v.sram_dest_reg_714.CAO_Dest = target; 50 + if (dest & FC_SRAM_DEST_MEDIA) 51 + v.sram_dest_reg_714.MEDIA_Dest = target; 52 + 53 + fc->write_ibi_reg(fc,sram_dest_reg_714,v); 54 + udelay(1000); /* TODO delay really necessary */ 55 + 56 + return 0; 57 + } 58 + EXPORT_SYMBOL(flexcop_sram_set_dest); 59 + 60 + void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s) 61 + { 62 + flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s); 63 + } 64 + EXPORT_SYMBOL(flexcop_wan_set_speed); 65 + 66 + void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill) 67 + { 68 + flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); 69 + v.sram_dest_reg_714.ctrl_usb_wan = usb_wan; 70 + v.sram_dest_reg_714.ctrl_sramdma = sramdma; 71 + v.sram_dest_reg_714.ctrl_maximumfill = maximumfill; 72 + fc->write_ibi_reg(fc,sram_dest_reg_714,v); 73 + } 74 + EXPORT_SYMBOL(flexcop_sram_ctrl); 75 + 76 + #if 0 77 + static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len) 78 + { 79 + int i, retries; 80 + u32 command; 81 + 82 + for (i = 0; i < len; i++) { 83 + command = bank | addr | 0x04000000 | (*buf << 0x10); 84 + 85 + retries = 2; 86 + 87 + while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { 88 + mdelay(1); 89 + retries--; 90 + }; 91 + 92 + if (retries == 0) 93 + printk("%s: SRAM timeout\n", __FUNCTION__); 94 + 95 + write_reg_dw(adapter, 0x700, command); 96 + 97 + buf++; 98 + addr++; 99 + } 100 + } 101 + 102 + static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len) 103 + { 104 + int i, retries; 105 + u32 command, value; 106 + 107 + for (i = 0; i < len; i++) { 108 + command = bank | addr | 0x04008000; 109 + 110 + retries = 10000; 111 + 112 + while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { 113 + mdelay(1); 114 + retries--; 115 + }; 116 + 117 + if (retries == 0) 118 + printk("%s: SRAM timeout\n", __FUNCTION__); 119 + 120 + write_reg_dw(adapter, 0x700, command); 121 + 122 + retries = 10000; 123 + 124 + while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { 125 + mdelay(1); 126 + retries--; 127 + }; 128 + 129 + if (retries == 0) 130 + printk("%s: SRAM timeout\n", __FUNCTION__); 131 + 132 + value = read_reg_dw(adapter, 0x700) >> 0x10; 133 + 134 + *buf = (value & 0xff); 135 + 136 + addr++; 137 + buf++; 138 + } 139 + } 140 + 141 + static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) 142 + { 143 + u32 bank; 144 + 145 + bank = 0; 146 + 147 + if (adapter->dw_sram_type == 0x20000) { 148 + bank = (addr & 0x18000) << 0x0d; 149 + } 150 + 151 + if (adapter->dw_sram_type == 0x00000) { 152 + if ((addr >> 0x0f) == 0) 153 + bank = 0x20000000; 154 + else 155 + bank = 0x10000000; 156 + } 157 + 158 + flex_sram_write(adapter, bank, addr & 0x7fff, buf, len); 159 + } 160 + 161 + static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) 162 + { 163 + u32 bank; 164 + 165 + bank = 0; 166 + 167 + if (adapter->dw_sram_type == 0x20000) { 168 + bank = (addr & 0x18000) << 0x0d; 169 + } 170 + 171 + if (adapter->dw_sram_type == 0x00000) { 172 + if ((addr >> 0x0f) == 0) 173 + bank = 0x20000000; 174 + else 175 + bank = 0x10000000; 176 + } 177 + 178 + flex_sram_read(adapter, bank, addr & 0x7fff, buf, len); 179 + } 180 + 181 + static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len) 182 + { 183 + u32 length; 184 + 185 + while (len != 0) { 186 + length = len; 187 + 188 + // check if the address range belongs to the same 189 + // 32K memory chip. If not, the data is read from 190 + // one chip at a time. 191 + if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { 192 + length = (((addr >> 0x0f) + 1) << 0x0f) - addr; 193 + } 194 + 195 + sram_read_chunk(adapter, addr, buf, length); 196 + 197 + addr = addr + length; 198 + buf = buf + length; 199 + len = len - length; 200 + } 201 + } 202 + 203 + static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len) 204 + { 205 + u32 length; 206 + 207 + while (len != 0) { 208 + length = len; 209 + 210 + // check if the address range belongs to the same 211 + // 32K memory chip. If not, the data is written to 212 + // one chip at a time. 213 + if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { 214 + length = (((addr >> 0x0f) + 1) << 0x0f) - addr; 215 + } 216 + 217 + sram_write_chunk(adapter, addr, buf, length); 218 + 219 + addr = addr + length; 220 + buf = buf + length; 221 + len = len - length; 222 + } 223 + } 224 + 225 + static void sram_set_size(struct adapter *adapter, u32 mask) 226 + { 227 + write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c)))); 228 + } 229 + 230 + static void sram_init(struct adapter *adapter) 231 + { 232 + u32 tmp; 233 + 234 + tmp = read_reg_dw(adapter, 0x71c); 235 + 236 + write_reg_dw(adapter, 0x71c, 1); 237 + 238 + if (read_reg_dw(adapter, 0x71c) != 0) { 239 + write_reg_dw(adapter, 0x71c, tmp); 240 + 241 + adapter->dw_sram_type = tmp & 0x30000; 242 + 243 + ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type); 244 + 245 + } else { 246 + 247 + adapter->dw_sram_type = 0x10000; 248 + 249 + ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type); 250 + } 251 + 252 + /* return value is never used? */ 253 + /* return adapter->dw_sram_type; */ 254 + } 255 + 256 + static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) 257 + { 258 + u8 tmp1, tmp2; 259 + 260 + dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr); 261 + 262 + sram_set_size(adapter, mask); 263 + sram_init(adapter); 264 + 265 + tmp2 = 0xa5; 266 + tmp1 = 0x4f; 267 + 268 + sram_write(adapter, addr, &tmp2, 1); 269 + sram_write(adapter, addr + 4, &tmp1, 1); 270 + 271 + tmp2 = 0; 272 + 273 + mdelay(20); 274 + 275 + sram_read(adapter, addr, &tmp2, 1); 276 + sram_read(adapter, addr, &tmp2, 1); 277 + 278 + dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2); 279 + 280 + if (tmp2 != 0xa5) 281 + return 0; 282 + 283 + tmp2 = 0x5a; 284 + tmp1 = 0xf4; 285 + 286 + sram_write(adapter, addr, &tmp2, 1); 287 + sram_write(adapter, addr + 4, &tmp1, 1); 288 + 289 + tmp2 = 0; 290 + 291 + mdelay(20); 292 + 293 + sram_read(adapter, addr, &tmp2, 1); 294 + sram_read(adapter, addr, &tmp2, 1); 295 + 296 + dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2); 297 + 298 + if (tmp2 != 0x5a) 299 + return 0; 300 + 301 + return 1; 302 + } 303 + 304 + static u32 sram_length(struct adapter *adapter) 305 + { 306 + if (adapter->dw_sram_type == 0x10000) 307 + return 32768; // 32K 308 + if (adapter->dw_sram_type == 0x00000) 309 + return 65536; // 64K 310 + if (adapter->dw_sram_type == 0x20000) 311 + return 131072; // 128K 312 + 313 + return 32768; // 32K 314 + } 315 + 316 + /* FlexcopII can work with 32K, 64K or 128K of external SRAM memory. 317 + - for 128K there are 4x32K chips at bank 0,1,2,3. 318 + - for 64K there are 2x32K chips at bank 1,2. 319 + - for 32K there is one 32K chip at bank 0. 320 + 321 + FlexCop works only with one bank at a time. The bank is selected 322 + by bits 28-29 of the 0x700 register. 323 + 324 + bank 0 covers addresses 0x00000-0x07fff 325 + bank 1 covers addresses 0x08000-0x0ffff 326 + bank 2 covers addresses 0x10000-0x17fff 327 + bank 3 covers addresses 0x18000-0x1ffff 328 + */ 329 + 330 + static int flexcop_sram_detect(struct flexcop_device *fc) 331 + { 332 + flexcop_ibi_value r208,r71c_0,vr71c_1; 333 + 334 + r208 = fc->read_ibi_reg(fc, ctrl_208); 335 + fc->write_ibi_reg(fc, ctrl_208, ibi_zero); 336 + 337 + r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c); 338 + 339 + write_reg_dw(adapter, 0x71c, 1); 340 + 341 + tmp3 = read_reg_dw(adapter, 0x71c); 342 + 343 + dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3); 344 + 345 + write_reg_dw(adapter, 0x71c, tmp2); 346 + 347 + // check for internal SRAM ??? 348 + tmp3--; 349 + if (tmp3 != 0) { 350 + sram_set_size(adapter, 0x10000); 351 + sram_init(adapter); 352 + write_reg_dw(adapter, 0x208, tmp); 353 + 354 + dprintk("%s: sram size = 32K\n", __FUNCTION__); 355 + 356 + return 32; 357 + } 358 + 359 + if (sram_test_location(adapter, 0x20000, 0x18000) != 0) { 360 + sram_set_size(adapter, 0x20000); 361 + sram_init(adapter); 362 + write_reg_dw(adapter, 0x208, tmp); 363 + 364 + dprintk("%s: sram size = 128K\n", __FUNCTION__); 365 + 366 + return 128; 367 + } 368 + 369 + if (sram_test_location(adapter, 0x00000, 0x10000) != 0) { 370 + sram_set_size(adapter, 0x00000); 371 + sram_init(adapter); 372 + write_reg_dw(adapter, 0x208, tmp); 373 + 374 + dprintk("%s: sram size = 64K\n", __FUNCTION__); 375 + 376 + return 64; 377 + } 378 + 379 + if (sram_test_location(adapter, 0x10000, 0x00000) != 0) { 380 + sram_set_size(adapter, 0x10000); 381 + sram_init(adapter); 382 + write_reg_dw(adapter, 0x208, tmp); 383 + 384 + dprintk("%s: sram size = 32K\n", __FUNCTION__); 385 + 386 + return 32; 387 + } 388 + 389 + sram_set_size(adapter, 0x10000); 390 + sram_init(adapter); 391 + write_reg_dw(adapter, 0x208, tmp); 392 + 393 + dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__); 394 + 395 + return 0; 396 + } 397 + 398 + static void sll_detect_sram_size(struct adapter *adapter) 399 + { 400 + sram_detect_for_flex2(adapter); 401 + } 402 + 403 + #endif
+530
drivers/media/dvb/b2c2/flexcop-usb.c
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop-usb.c - covers the USB part. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + 9 + #define FC_LOG_PREFIX "flexcop_usb" 10 + #include "flexcop-usb.h" 11 + #include "flexcop-common.h" 12 + 13 + /* Version information */ 14 + #define DRIVER_VERSION "0.1" 15 + #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver" 16 + #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>" 17 + 18 + /* debug */ 19 + #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG 20 + #define dprintk(level,args...) \ 21 + do { if ((debug & level)) { printk(args); } } while (0) 22 + #define debug_dump(b,l,method) {\ 23 + int i; \ 24 + for (i = 0; i < l; i++) method("%02x ", b[i]); \ 25 + method("\n");\ 26 + } 27 + 28 + #define DEBSTATUS "" 29 + #else 30 + #define dprintk(level,args...) 31 + #define debug_dump(b,l,method) 32 + #define DEBSTATUS " (debugging is not enabled)" 33 + #endif 34 + 35 + static int debug; 36 + module_param(debug, int, 0644); 37 + MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,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 (these are 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) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70)) 56 + #define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4)) 57 + 58 + /* 59 + * DKT 020228 60 + * - forget about this VENDOR_BUFFER_SIZE, read and write register 61 + * deal with DWORD or 4 bytes, that should be should from now on 62 + * - from now on, we don't support anything older than firm 1.00 63 + * I eliminated the write register as a 2 trip of writing hi word and lo word 64 + * and force this to write only 4 bytes at a time. 65 + * NOTE: this should work with all the firmware from 1.00 and newer 66 + */ 67 + static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, u32 *val, u8 read) 68 + { 69 + struct flexcop_usb *fc_usb = fc->bus_specific; 70 + u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG; 71 + u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; 72 + u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | (read ? 0x80 : 0); 73 + 74 + int len = usb_control_msg(fc_usb->udev, 75 + read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, 76 + request, 77 + request_type, /* 0xc0 read or 0x40 write*/ 78 + wAddress, 79 + 0, 80 + val, 81 + sizeof(u32), 82 + B2C2_WAIT_FOR_OPERATION_RDW * HZ); 83 + 84 + if (len != sizeof(u32)) { 85 + err("error while %s dword from %d (%d).",read ? "reading" : "writing", 86 + wAddress,wRegOffsPCI); 87 + return -EIO; 88 + } 89 + return 0; 90 + } 91 + 92 + /* 93 + * DKT 010817 - add support for V8 memory read/write and flash update 94 + */ 95 + static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, 96 + flexcop_usb_request_t req, u8 page, u16 wAddress, 97 + u8 *pbBuffer,u32 buflen) 98 + { 99 + // u8 dwRequestType; 100 + u8 request_type = USB_TYPE_VENDOR; 101 + u16 wIndex; 102 + int nWaitTime,pipe,len; 103 + 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 + // dwRequestType = (u8) RTYPE_READ_V8_MEMORY; 111 + pipe = B2C2_USB_CTRL_PIPE_IN; 112 + break; 113 + case B2C2_USB_WRITE_V8_MEM: 114 + wIndex |= pbBuffer[0]; 115 + request_type |= USB_DIR_OUT; 116 + nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE; 117 + // dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY; 118 + pipe = B2C2_USB_CTRL_PIPE_OUT; 119 + break; 120 + case B2C2_USB_FLASH_BLOCK: 121 + request_type |= USB_DIR_OUT; 122 + nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH; 123 + // dwRequestType = (u8) RTYPE_WRITE_V8_FLASH; 124 + pipe = B2C2_USB_CTRL_PIPE_OUT; 125 + break; 126 + default: 127 + deb_info("unsupported request for v8_mem_req %x.\n",req); 128 + return -EINVAL; 129 + } 130 + deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req, 131 + wAddress,wIndex,buflen); 132 + 133 + len = usb_control_msg(fc_usb->udev,pipe, 134 + req, 135 + request_type, 136 + wAddress, 137 + wIndex, 138 + pbBuffer, 139 + buflen, 140 + nWaitTime * HZ); 141 + 142 + debug_dump(pbBuffer,len,deb_v8); 143 + 144 + return len == buflen ? 0 : -EIO; 145 + } 146 + 147 + #define bytes_left_to_read_on_page(paddr,buflen) \ 148 + ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ 149 + ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK))) 150 + 151 + static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request_t req, 152 + flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len) 153 + { 154 + int i,ret = 0; 155 + u16 wMax; 156 + u32 pagechunk = 0; 157 + 158 + switch(req) { 159 + case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break; 160 + case B2C2_USB_WRITE_V8_MEM: wMax = USB_MEM_WRITE_MAX; break; 161 + case B2C2_USB_FLASH_BLOCK: wMax = USB_FLASH_MAX; break; 162 + default: 163 + return -EINVAL; 164 + break; 165 + } 166 + for (i = 0; i < len;) { 167 + pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len); 168 + deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended)); 169 + if ((ret = flexcop_usb_v8_memory_req(fc_usb,req, 170 + page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */ 171 + (addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended), 172 + &buf[i],pagechunk)) < 0) 173 + return ret; 174 + 175 + addr += pagechunk; 176 + len -= pagechunk; 177 + } 178 + return 0; 179 + } 180 + 181 + static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended) 182 + { 183 + return flexcop_usb_memory_req(fc->bus_specific,B2C2_USB_READ_V8_MEM,V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->mac_address,6); 184 + } 185 + 186 + #if 0 187 + static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, 188 + flexcop_usb_utility_function_t func, u8 extra, u16 wIndex, 189 + u16 buflen, u8 *pvBuffer) 190 + { 191 + u16 wValue; 192 + u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; 193 + // u8 dwRequestType = (u8) RTYPE_GENERIC, 194 + int nWaitTime = 2, 195 + pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, 196 + len; 197 + 198 + wValue = (func << 8) | extra; 199 + 200 + len = usb_control_msg(fc_usb->udev,pipe, 201 + B2C2_USB_UTILITY, 202 + request_type, 203 + wValue, 204 + wIndex, 205 + pvBuffer, 206 + buflen, 207 + nWaitTime * HZ); 208 + return len == buflen ? 0 : -EIO; 209 + } 210 + #endif 211 + 212 + /* usb i2c stuff */ 213 + static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb, 214 + flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, 215 + flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen) 216 + { 217 + u16 wValue, wIndex; 218 + int nWaitTime,pipe,len; 219 + // u8 dwRequestType; 220 + u8 request_type = USB_TYPE_VENDOR; 221 + 222 + switch (func) { 223 + case USB_FUNC_I2C_WRITE: 224 + case USB_FUNC_I2C_MULTIWRITE: 225 + case USB_FUNC_I2C_REPEATWRITE: 226 + /* DKT 020208 - add this to support special case of DiSEqC */ 227 + case USB_FUNC_I2C_CHECKWRITE: 228 + pipe = B2C2_USB_CTRL_PIPE_OUT; 229 + nWaitTime = 2; 230 + // dwRequestType = (u8) RTYPE_GENERIC; 231 + request_type |= USB_DIR_OUT; 232 + break; 233 + case USB_FUNC_I2C_READ: 234 + case USB_FUNC_I2C_REPEATREAD: 235 + pipe = B2C2_USB_CTRL_PIPE_IN; 236 + nWaitTime = 2; 237 + // dwRequestType = (u8) RTYPE_GENERIC; 238 + request_type |= USB_DIR_IN; 239 + break; 240 + default: 241 + deb_info("unsupported function for i2c_req %x\n",func); 242 + return -EINVAL; 243 + } 244 + wValue = (func << 8 ) | (port << 4); 245 + wIndex = (chipaddr << 8 ) | addr; 246 + 247 + deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req, 248 + ((wValue && 0xff) << 8),wValue >> 8,((wIndex && 0xff) << 8),wIndex >> 8); 249 + 250 + len = usb_control_msg(fc_usb->udev,pipe, 251 + req, 252 + request_type, 253 + wValue, 254 + wIndex, 255 + buf, 256 + buflen, 257 + nWaitTime * HZ); 258 + 259 + return len == buflen ? 0 : -EREMOTEIO; 260 + } 261 + 262 + /* actual bus specific access functions, make sure prototype are/will be equal to pci */ 263 + static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg) 264 + { 265 + flexcop_ibi_value val; 266 + val.raw = 0; 267 + flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1); 268 + return val; 269 + } 270 + 271 + static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg, flexcop_ibi_value val) 272 + { 273 + return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0); 274 + } 275 + 276 + static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, 277 + flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len) 278 + { 279 + if (op == FC_READ) 280 + return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len); 281 + else 282 + return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len); 283 + } 284 + 285 + static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs) 286 + { 287 + struct flexcop_usb *fc_usb = urb->context; 288 + int i; 289 + 290 + if (urb->actual_length > 0) 291 + deb_ts("urb completed, bufsize: %d actlen; %d\n",urb->transfer_buffer_length, urb->actual_length); 292 + 293 + for (i = 0; i < urb->number_of_packets; i++) { 294 + if (urb->iso_frame_desc[i].status < 0) { 295 + err("iso frame descriptor %d has an error: %d\n",i,urb->iso_frame_desc[i].status); 296 + } else 297 + if (urb->iso_frame_desc[i].actual_length > 0) { 298 + deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length); 299 + 300 + flexcop_pass_dmx_data(fc_usb->fc_dev, 301 + urb->transfer_buffer + urb->iso_frame_desc[i].offset, 302 + urb->iso_frame_desc[i].actual_length); 303 + } 304 + urb->iso_frame_desc[i].status = 0; 305 + urb->iso_frame_desc[i].actual_length = 0; 306 + } 307 + 308 + usb_submit_urb(urb,GFP_ATOMIC); 309 + } 310 + 311 + static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff) 312 + { 313 + /* submit/kill iso packets */ 314 + return 0; 315 + } 316 + 317 + static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb) 318 + { 319 + int i; 320 + for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) 321 + if (fc_usb->iso_urb[i] != NULL) { 322 + deb_ts("unlinking/killing urb no. %d\n",i); 323 + usb_kill_urb(fc_usb->iso_urb[i]); 324 + usb_free_urb(fc_usb->iso_urb[i]); 325 + } 326 + 327 + if (fc_usb->iso_buffer != NULL) 328 + pci_free_consistent(NULL,fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr); 329 + } 330 + 331 + static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) 332 + { 333 + u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize; 334 + int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret; 335 + int buffer_offset = 0; 336 + 337 + deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n", 338 + B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize); 339 + 340 + fc_usb->iso_buffer = pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr); 341 + if (fc_usb->iso_buffer == NULL) 342 + return -ENOMEM; 343 + memset(fc_usb->iso_buffer, 0, bufsize); 344 + fc_usb->buffer_size = bufsize; 345 + 346 + /* creating iso urbs */ 347 + for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) 348 + if (!(fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) { 349 + ret = -ENOMEM; 350 + goto urb_error; 351 + } 352 + /* initialising and submitting iso urbs */ 353 + for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { 354 + int frame_offset = 0; 355 + struct urb *urb = fc_usb->iso_urb[i]; 356 + deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset); 357 + 358 + urb->dev = fc_usb->udev; 359 + urb->context = fc_usb; 360 + urb->complete = flexcop_usb_urb_complete; 361 + urb->pipe = B2C2_USB_DATA_PIPE; 362 + urb->transfer_flags = URB_ISO_ASAP; 363 + urb->interval = 1; 364 + urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO; 365 + urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO; 366 + urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset; 367 + 368 + buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO; 369 + for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) { 370 + deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset); 371 + urb->iso_frame_desc[j].offset = frame_offset; 372 + urb->iso_frame_desc[j].length = frame_size; 373 + frame_offset += frame_size; 374 + } 375 + 376 + if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) { 377 + err("submitting urb %d failed with %d.",i,ret); 378 + goto urb_error; 379 + } 380 + deb_ts("submitted urb no. %d.\n",i); 381 + } 382 + 383 + /* SRAM */ 384 + 385 + flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET | 386 + FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB); 387 + flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS); 388 + flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1); 389 + 390 + ret = 0; 391 + goto success; 392 + urb_error: 393 + flexcop_usb_transfer_exit(fc_usb); 394 + success: 395 + return ret; 396 + } 397 + 398 + static int flexcop_usb_init(struct flexcop_usb *fc_usb) 399 + { 400 + /* use the alternate setting with the larges buffer */ 401 + usb_set_interface(fc_usb->udev,0,1); 402 + switch (fc_usb->udev->speed) { 403 + case USB_SPEED_LOW: 404 + err("cannot handle USB speed because it is to sLOW."); 405 + return -ENODEV; 406 + break; 407 + case USB_SPEED_FULL: 408 + info("running at FULL speed."); 409 + break; 410 + case USB_SPEED_HIGH: 411 + info("running at HIGH speed."); 412 + break; 413 + case USB_SPEED_UNKNOWN: /* fall through */ 414 + default: 415 + err("cannot handle USB speed because it is unkown."); 416 + return -ENODEV; 417 + } 418 + usb_set_intfdata(fc_usb->uintf, fc_usb); 419 + return 0; 420 + } 421 + 422 + static void flexcop_usb_exit(struct flexcop_usb *fc_usb) 423 + { 424 + usb_set_intfdata(fc_usb->uintf, NULL); 425 + } 426 + 427 + static int flexcop_usb_probe(struct usb_interface *intf, 428 + const struct usb_device_id *id) 429 + { 430 + struct usb_device *udev = interface_to_usbdev(intf); 431 + struct flexcop_usb *fc_usb = NULL; 432 + struct flexcop_device *fc = NULL; 433 + int ret; 434 + 435 + if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { 436 + err("out of memory\n"); 437 + return -ENOMEM; 438 + } 439 + 440 + /* general flexcop init */ 441 + fc_usb = fc->bus_specific; 442 + fc_usb->fc_dev = fc; 443 + 444 + fc->read_ibi_reg = flexcop_usb_read_ibi_reg; 445 + fc->write_ibi_reg = flexcop_usb_write_ibi_reg; 446 + fc->i2c_request = flexcop_usb_i2c_request; 447 + fc->get_mac_addr = flexcop_usb_get_mac_addr; 448 + 449 + fc->stream_control = flexcop_usb_stream_control; 450 + 451 + fc->pid_filtering = 1; 452 + fc->bus_type = FC_USB; 453 + 454 + fc->dev = &udev->dev; 455 + 456 + /* bus specific part */ 457 + fc_usb->udev = udev; 458 + fc_usb->uintf = intf; 459 + if ((ret = flexcop_usb_init(fc_usb)) != 0) 460 + goto err_kfree; 461 + 462 + /* init flexcop */ 463 + if ((ret = flexcop_device_initialize(fc)) != 0) 464 + goto err_usb_exit; 465 + 466 + /* xfer init */ 467 + if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0) 468 + goto err_fc_exit; 469 + 470 + info("%s successfully initialized and connected.",DRIVER_NAME); 471 + ret = 0; 472 + goto success; 473 + err_fc_exit: 474 + flexcop_device_exit(fc); 475 + err_usb_exit: 476 + flexcop_usb_exit(fc_usb); 477 + err_kfree: 478 + flexcop_device_kfree(fc); 479 + success: 480 + return ret; 481 + } 482 + 483 + static void flexcop_usb_disconnect(struct usb_interface *intf) 484 + { 485 + struct flexcop_usb *fc_usb = usb_get_intfdata(intf); 486 + flexcop_usb_transfer_exit(fc_usb); 487 + flexcop_device_exit(fc_usb->fc_dev); 488 + flexcop_usb_exit(fc_usb); 489 + flexcop_device_kfree(fc_usb->fc_dev); 490 + info("%s successfully deinitialized and disconnected.",DRIVER_NAME); 491 + } 492 + 493 + static struct usb_device_id flexcop_usb_table [] = { 494 + { USB_DEVICE(0x0af7, 0x0101) }, 495 + { } 496 + }; 497 + 498 + /* usb specific object needed to register this driver with the usb subsystem */ 499 + static struct usb_driver flexcop_usb_driver = { 500 + .owner = THIS_MODULE, 501 + .name = "Technisat/B2C2 FlexCop II/IIb/III USB", 502 + .probe = flexcop_usb_probe, 503 + .disconnect = flexcop_usb_disconnect, 504 + .id_table = flexcop_usb_table, 505 + }; 506 + 507 + /* module stuff */ 508 + static int __init flexcop_usb_module_init(void) 509 + { 510 + int result; 511 + if ((result = usb_register(&flexcop_usb_driver))) { 512 + err("usb_register failed. (%d)",result); 513 + return result; 514 + } 515 + 516 + return 0; 517 + } 518 + 519 + static void __exit flexcop_usb_module_exit(void) 520 + { 521 + /* deregister this driver from the USB subsystem */ 522 + usb_deregister(&flexcop_usb_driver); 523 + } 524 + 525 + module_init(flexcop_usb_module_init); 526 + module_exit(flexcop_usb_module_exit); 527 + 528 + MODULE_AUTHOR(DRIVER_AUTHOR); 529 + MODULE_DESCRIPTION(DRIVER_NAME); 530 + MODULE_LICENSE("GPL");
+116
drivers/media/dvb/b2c2/flexcop-usb.h
··· 1 + #ifndef __FLEXCOP_USB_H_INCLUDED__ 2 + #define __FLEXCOP_USB_H_INCLUDED__ 3 + 4 + #include <linux/usb.h> 5 + 6 + /* transfer parameters */ 7 + #define B2C2_USB_FRAMES_PER_ISO 4 8 + #define B2C2_USB_NUM_ISO_URB 4 9 + 10 + #define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev,0) 11 + #define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev,0) 12 + #define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev,0x81) 13 + 14 + struct flexcop_usb { 15 + struct usb_device *udev; 16 + struct usb_interface *uintf; 17 + 18 + u8 *iso_buffer; 19 + int buffer_size; 20 + dma_addr_t dma_addr; 21 + struct urb *iso_urb[B2C2_USB_NUM_ISO_URB]; 22 + 23 + struct flexcop_device *fc_dev; 24 + }; 25 + 26 + #if 0 27 + /* request types TODO What is its use?*/ 28 + typedef enum { 29 + 30 + /* something is wrong with this part 31 + RTYPE_READ_DW = (1 << 6), 32 + RTYPE_WRITE_DW_1 = (3 << 6), 33 + RTYPE_READ_V8_MEMORY = (6 << 6), 34 + RTYPE_WRITE_V8_MEMORY = (7 << 6), 35 + RTYPE_WRITE_V8_FLASH = (8 << 6), 36 + RTYPE_GENERIC = (9 << 6), 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_WRITEREGLO = 0x0A, */ 48 + B2C2_USB_WRITEREGHI = 0x0B, 49 + B2C2_USB_FLASH_BLOCK = 0x10, 50 + B2C2_USB_I2C_REQUEST = 0x11, 51 + B2C2_USB_UTILITY = 0x12, 52 + } flexcop_usb_request_t; 53 + 54 + /* function definition for I2C_REQUEST */ 55 + typedef enum { 56 + USB_FUNC_I2C_WRITE = 0x01, 57 + USB_FUNC_I2C_MULTIWRITE = 0x02, 58 + USB_FUNC_I2C_READ = 0x03, 59 + USB_FUNC_I2C_REPEATWRITE = 0x04, 60 + USB_FUNC_GET_DESCRIPTOR = 0x05, 61 + USB_FUNC_I2C_REPEATREAD = 0x06, 62 + /* DKT 020208 - add this to support special case of DiSEqC */ 63 + USB_FUNC_I2C_CHECKWRITE = 0x07, 64 + USB_FUNC_I2C_CHECKRESULT = 0x08, 65 + } flexcop_usb_i2c_function_t; 66 + 67 + /* 68 + * function definition for UTILITY request 0x12 69 + * DKT 020304 - new utility function 70 + */ 71 + typedef enum { 72 + UTILITY_SET_FILTER = 0x01, 73 + UTILITY_DATA_ENABLE = 0x02, 74 + UTILITY_FLEX_MULTIWRITE = 0x03, 75 + UTILITY_SET_BUFFER_SIZE = 0x04, 76 + UTILITY_FLEX_OPERATOR = 0x05, 77 + UTILITY_FLEX_RESET300_START = 0x06, 78 + UTILITY_FLEX_RESET300_STOP = 0x07, 79 + UTILITY_FLEX_RESET300 = 0x08, 80 + UTILITY_SET_ISO_SIZE = 0x09, 81 + UTILITY_DATA_RESET = 0x0A, 82 + UTILITY_GET_DATA_STATUS = 0x10, 83 + UTILITY_GET_V8_REG = 0x11, 84 + /* DKT 020326 - add function for v1.14 */ 85 + UTILITY_SRAM_WRITE = 0x12, 86 + UTILITY_SRAM_READ = 0x13, 87 + UTILITY_SRAM_TESTFILL = 0x14, 88 + UTILITY_SRAM_TESTSET = 0x15, 89 + UTILITY_SRAM_TESTVERIFY = 0x16, 90 + } flexcop_usb_utility_function_t; 91 + 92 + #define B2C2_WAIT_FOR_OPERATION_RW 1*HZ /* 1 s */ 93 + #define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ /* 3 s */ 94 + #define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ /* 1 s */ 95 + 96 + #define B2C2_WAIT_FOR_OPERATION_V8READ 3*HZ /* 3 s */ 97 + #define B2C2_WAIT_FOR_OPERATION_V8WRITE 3*HZ /* 3 s */ 98 + #define B2C2_WAIT_FOR_OPERATION_V8FLASH 3*HZ /* 3 s */ 99 + 100 + typedef enum { 101 + V8_MEMORY_PAGE_DVB_CI = 0x20, 102 + V8_MEMORY_PAGE_DVB_DS = 0x40, 103 + V8_MEMORY_PAGE_MULTI2 = 0x60, 104 + V8_MEMORY_PAGE_FLASH = 0x80 105 + } flexcop_usb_mem_page_t; 106 + 107 + #define V8_MEMORY_EXTENDED (1 << 15) 108 + 109 + #define USB_MEM_READ_MAX 32 110 + #define USB_MEM_WRITE_MAX 1 111 + #define USB_FLASH_MAX 8 112 + 113 + #define V8_MEMORY_PAGE_SIZE 0x8000 // 32K 114 + #define V8_MEMORY_PAGE_MASK 0x7FFF 115 + 116 + #endif
+288
drivers/media/dvb/b2c2/flexcop.c
··· 1 + /* 2 + * flexcop.c - driver for digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * Copyright (C) 2004-5 Patrick Boettcher <patrick.boettcher@desy.de> 5 + * 6 + * based on the skystar2-driver 7 + * Copyright (C) 2003 Vadim Catana, skystar@moldova.cc 8 + * 9 + * Acknowledgements: 10 + * John Jurrius from BBTI, Inc. for extensive support with 11 + * code examples and data books 12 + * 13 + * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting) 14 + * 15 + * Contributions to the skystar2-driver have been done by 16 + * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes) 17 + * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code) 18 + * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac filtering) 19 + * 20 + * 21 + * This program is free software; you can redistribute it and/or 22 + * modify it under the terms of the GNU Lesser General Public License 23 + * as published by the Free Software Foundation; either version 2.1 24 + * of the License, or (at your option) any later version. 25 + * 26 + * This program is distributed in the hope that it will be useful, 27 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 + * GNU General Public License for more details. 30 + * 31 + * You should have received a copy of the GNU Lesser General Public License 32 + * along with this program; if not, write to the Free Software 33 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 34 + */ 35 + 36 + #include "flexcop.h" 37 + 38 + #define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip" 39 + #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de" 40 + 41 + #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG 42 + #define DEBSTATUS "" 43 + #else 44 + #define DEBSTATUS " (debugging is not enabled)" 45 + #endif 46 + 47 + int b2c2_flexcop_debug; 48 + module_param_named(debug, b2c2_flexcop_debug, int, 0644); 49 + MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram (|-able))." DEBSTATUS); 50 + #undef DEBSTATUS 51 + 52 + /* global zero for ibi values */ 53 + flexcop_ibi_value ibi_zero; 54 + 55 + static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) 56 + { 57 + struct flexcop_device *fc = dvbdmxfeed->demux->priv; 58 + return flexcop_pid_feed_control(fc,dvbdmxfeed,1); 59 + } 60 + 61 + static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 62 + { 63 + struct flexcop_device *fc = dvbdmxfeed->demux->priv; 64 + return flexcop_pid_feed_control(fc,dvbdmxfeed,0); 65 + } 66 + 67 + static int flexcop_dvb_init(struct flexcop_device *fc) 68 + { 69 + int ret; 70 + if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",THIS_MODULE)) < 0) { 71 + err("error registering DVB adapter"); 72 + return ret; 73 + } 74 + fc->dvb_adapter.priv = fc; 75 + 76 + fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); 77 + fc->demux.priv = fc; 78 + 79 + fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED; 80 + 81 + fc->demux.start_feed = flexcop_dvb_start_feed; 82 + fc->demux.stop_feed = flexcop_dvb_stop_feed; 83 + fc->demux.write_to_decoder = NULL; 84 + 85 + if ((ret = dvb_dmx_init(&fc->demux)) < 0) { 86 + err("dvb_dmx failed: error %d",ret); 87 + goto err_dmx; 88 + } 89 + 90 + fc->hw_frontend.source = DMX_FRONTEND_0; 91 + 92 + fc->dmxdev.filternum = fc->demux.feednum; 93 + fc->dmxdev.demux = &fc->demux.dmx; 94 + fc->dmxdev.capabilities = 0; 95 + if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) { 96 + err("dvb_dmxdev_init failed: error %d",ret); 97 + goto err_dmx_dev; 98 + } 99 + 100 + if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) { 101 + err("adding hw_frontend to dmx failed: error %d",ret); 102 + goto err_dmx_add_hw_frontend; 103 + } 104 + 105 + fc->mem_frontend.source = DMX_MEMORY_FE; 106 + if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) { 107 + err("adding mem_frontend to dmx failed: error %d",ret); 108 + goto err_dmx_add_mem_frontend; 109 + } 110 + 111 + if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) { 112 + err("connect frontend failed: error %d",ret); 113 + goto err_connect_frontend; 114 + } 115 + 116 + dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx); 117 + 118 + fc->init_state |= FC_STATE_DVB_INIT; 119 + goto success; 120 + 121 + err_connect_frontend: 122 + fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); 123 + err_dmx_add_mem_frontend: 124 + fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend); 125 + err_dmx_add_hw_frontend: 126 + dvb_dmxdev_release(&fc->dmxdev); 127 + err_dmx_dev: 128 + dvb_dmx_release(&fc->demux); 129 + err_dmx: 130 + dvb_unregister_adapter(&fc->dvb_adapter); 131 + return ret; 132 + 133 + success: 134 + return 0; 135 + } 136 + 137 + static void flexcop_dvb_exit(struct flexcop_device *fc) 138 + { 139 + if (fc->init_state & FC_STATE_DVB_INIT) { 140 + dvb_net_release(&fc->dvbnet); 141 + 142 + fc->demux.dmx.close(&fc->demux.dmx); 143 + fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); 144 + fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend); 145 + dvb_dmxdev_release(&fc->dmxdev); 146 + dvb_dmx_release(&fc->demux); 147 + dvb_unregister_adapter(&fc->dvb_adapter); 148 + 149 + deb_info("deinitialized dvb stuff\n"); 150 + } 151 + fc->init_state &= ~FC_STATE_DVB_INIT; 152 + } 153 + 154 + /* these methods are necessary to achieve the long-term-goal of hiding the 155 + * struct flexcop_device from the bus-parts */ 156 + void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len) 157 + { 158 + dvb_dmx_swfilter(&fc->demux, buf, len); 159 + } 160 + EXPORT_SYMBOL(flexcop_pass_dmx_data); 161 + 162 + void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no) 163 + { 164 + dvb_dmx_swfilter_packets(&fc->demux, buf, no); 165 + } 166 + EXPORT_SYMBOL(flexcop_pass_dmx_packets); 167 + 168 + static void flexcop_reset(struct flexcop_device *fc) 169 + { 170 + flexcop_ibi_value v210,v204; 171 + 172 + /* reset the flexcop itself */ 173 + fc->write_ibi_reg(fc,ctrl_208,ibi_zero); 174 + 175 + v210.raw = 0; 176 + v210.sw_reset_210.reset_blocks = 0xff; 177 + v210.sw_reset_210.Block_reset_enable = 0xb2; 178 + fc->write_ibi_reg(fc,sw_reset_210,v210); 179 + 180 + /* reset the periphical devices */ 181 + 182 + v204 = fc->read_ibi_reg(fc,misc_204); 183 + v204.misc_204.Per_reset_sig = 0; 184 + fc->write_ibi_reg(fc,misc_204,v204); 185 + v204.misc_204.Per_reset_sig = 1; 186 + fc->write_ibi_reg(fc,misc_204,v204); 187 + 188 + /* v208.raw = 0; 189 + v208.ctrl_208.Null_filter_sig = 1; 190 + fc->write_ibi_reg(fc,ctrl_208,v208);*/ 191 + } 192 + 193 + struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) 194 + { 195 + void *bus; 196 + struct flexcop_device *fc = kmalloc(sizeof(struct flexcop_device), GFP_KERNEL); 197 + if (!fc) { 198 + err("no memory"); 199 + return NULL; 200 + } 201 + memset(fc, 0, sizeof(struct flexcop_device)); 202 + 203 + bus = kmalloc(bus_specific_len, GFP_KERNEL); 204 + if (!bus) { 205 + err("no memory"); 206 + kfree(fc); 207 + return NULL; 208 + } 209 + memset(bus, 0, bus_specific_len); 210 + 211 + fc->bus_specific = bus; 212 + 213 + return fc; 214 + } 215 + EXPORT_SYMBOL(flexcop_device_kmalloc); 216 + 217 + void flexcop_device_kfree(struct flexcop_device *fc) 218 + { 219 + kfree(fc->bus_specific); 220 + kfree(fc); 221 + } 222 + EXPORT_SYMBOL(flexcop_device_kfree); 223 + 224 + int flexcop_device_initialize(struct flexcop_device *fc) 225 + { 226 + int ret; 227 + ibi_zero.raw = 0; 228 + 229 + flexcop_reset(fc); 230 + flexcop_determine_revision(fc); 231 + flexcop_sram_init(fc); 232 + flexcop_hw_filter_init(fc); 233 + 234 + flexcop_smc_ctrl(fc, 0); 235 + 236 + if (fc->get_mac_addr(fc, 0) == 0) { 237 + u8 *b = fc->mac_address; 238 + info("MAC address = %02x:%02x:%02x:%02x:%02x:%02x", b[0],b[1],b[2],b[3],b[4],b[5]); 239 + flexcop_set_mac_filter(fc,fc->mac_address); 240 + flexcop_mac_filter_ctrl(fc,1); 241 + } else 242 + warn("reading of MAC address failed.\n"); 243 + 244 + if ((ret = flexcop_dvb_init(fc))) 245 + goto error; 246 + 247 + if ((ret = flexcop_i2c_init(fc))) 248 + goto error; 249 + 250 + if ((ret = flexcop_frontend_init(fc))) 251 + goto error; 252 + 253 + flexcop_device_name(fc,"initialization of","complete"); 254 + 255 + ret = 0; 256 + goto success; 257 + error: 258 + flexcop_device_exit(fc); 259 + success: 260 + return ret; 261 + } 262 + EXPORT_SYMBOL(flexcop_device_initialize); 263 + 264 + void flexcop_device_exit(struct flexcop_device *fc) 265 + { 266 + flexcop_frontend_exit(fc); 267 + flexcop_i2c_exit(fc); 268 + flexcop_dvb_exit(fc); 269 + } 270 + EXPORT_SYMBOL(flexcop_device_exit); 271 + 272 + static int flexcop_module_init(void) 273 + { 274 + info(DRIVER_NAME " loaded successfully"); 275 + return 0; 276 + } 277 + 278 + static void flexcop_module_cleanup(void) 279 + { 280 + info(DRIVER_NAME " unloaded successfully"); 281 + } 282 + 283 + module_init(flexcop_module_init); 284 + module_exit(flexcop_module_cleanup); 285 + 286 + MODULE_AUTHOR(DRIVER_AUTHOR); 287 + MODULE_DESCRIPTION(DRIVER_NAME); 288 + MODULE_LICENSE("GPL");
+30
drivers/media/dvb/b2c2/flexcop.h
··· 1 + /* 2 + * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 3 + * 4 + * flexcop.h - private header file for all flexcop-chip-source files. 5 + * 6 + * see flexcop.c for copyright information. 7 + */ 8 + #ifndef __FLEXCOP_H__ 9 + #define __FLEXCOP_H___ 10 + 11 + #define FC_LOG_PREFIX "b2c2-flexcop" 12 + #include "flexcop-common.h" 13 + 14 + extern int b2c2_flexcop_debug; 15 + 16 + /* debug */ 17 + #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG 18 + #define dprintk(level,args...) \ 19 + do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0) 20 + #else 21 + #define dprintk(level,args...) 22 + #endif 23 + 24 + #define deb_info(args...) dprintk(0x01,args) 25 + #define deb_tuner(args...) dprintk(0x02,args) 26 + #define deb_i2c(args...) dprintk(0x04,args) 27 + #define deb_ts(args...) dprintk(0x08,args) 28 + #define deb_sram(args...) dprintk(0x10,args) 29 + 30 + #endif