aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Stezenbach <js@linuxtv.org>2005-05-17 00:54:10 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-17 10:59:24 -0400
commit2add87a95068d6457d4e5824d0417d39007665a4 (patch)
treef2aa0373421b0bd78ce900a41fa5a72b853e66de /drivers
parent1ec359729960f7896db8f642454e603d22519d20 (diff)
[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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/Kconfig2
-rw-r--r--drivers/media/dvb/b2c2/Kconfig37
-rw-r--r--drivers/media/dvb/b2c2/Makefile11
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h161
-rw-r--r--drivers/media/dvb/b2c2/flexcop-dma.c149
-rw-r--r--drivers/media/dvb/b2c2/flexcop-eeprom.c157
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c403
-rw-r--r--drivers/media/dvb/b2c2/flexcop-hw-filter.c198
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c204
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c66
-rw-r--r--drivers/media/dvb/b2c2/flexcop-pci.c365
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h700
-rw-r--r--drivers/media/dvb/b2c2/flexcop-sram.c403
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c530
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.h116
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c288
-rw-r--r--drivers/media/dvb/b2c2/flexcop.h30
17 files changed, 3819 insertions, 1 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 883ec08490f4..4983e1b1bb1d 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -33,7 +33,7 @@ source "drivers/media/dvb/dibusb/Kconfig"
33source "drivers/media/dvb/cinergyT2/Kconfig" 33source "drivers/media/dvb/cinergyT2/Kconfig"
34 34
35comment "Supported FlexCopII (B2C2) Adapters" 35comment "Supported FlexCopII (B2C2) Adapters"
36 depends on DVB_CORE && PCI 36 depends on DVB_CORE && (PCI || USB)
37source "drivers/media/dvb/b2c2/Kconfig" 37source "drivers/media/dvb/b2c2/Kconfig"
38 38
39comment "Supported BT878 Adapters" 39comment "Supported BT878 Adapters"
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index f1f6187b7c1e..99bd675df955 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -1,3 +1,40 @@
1config 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
15config 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
23config 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
31config 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
1config DVB_B2C2_SKYSTAR 38config DVB_B2C2_SKYSTAR
2 tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI" 39 tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI"
3 depends on DVB_CORE && PCI 40 depends on DVB_CORE && PCI
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index f9cdc6f052d7..7703812af34f 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -1,3 +1,14 @@
1b2c2-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
4obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
5
6b2c2-flexcop-pci-objs = flexcop-pci.o
7obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
8
9b2c2-flexcop-usb-objs = flexcop-usb.o
10obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
11
1obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o 12obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o
2 13
3EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ 14EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
new file mode 100644
index 000000000000..82b7f8fa7b9c
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -0,0 +1,161 @@
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
37struct 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 */
50struct 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 */
99void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
100void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no);
101
102struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len);
103void flexcop_device_kfree(struct flexcop_device*);
104
105int flexcop_device_initialize(struct flexcop_device*);
106void flexcop_device_exit(struct flexcop_device *fc);
107
108/* from flexcop-dma.c */
109int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size);
110void flexcop_dma_free(struct flexcop_dma *dma);
111
112int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
113int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
114int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
115int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index);
116int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
117int 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 */
121int 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 */
128int 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 */
132int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
133void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s);
134void 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 */
138int flexcop_frontend_init(struct flexcop_device *card);
139void flexcop_frontend_exit(struct flexcop_device *fc);
140
141/* from flexcop-i2c.c */
142int flexcop_i2c_init(struct flexcop_device *fc);
143void flexcop_i2c_exit(struct flexcop_device *fc);
144
145/* from flexcop-sram.c */
146int flexcop_sram_init(struct flexcop_device *fc);
147
148/* from flexcop-misc.c */
149void flexcop_determine_revision(struct flexcop_device *fc);
150void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix);
151
152/* from flexcop-hw-filter.c */
153int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff);
154void flexcop_hw_filter_init(struct flexcop_device *fc);
155
156void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);
157
158void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
159void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff);
160
161#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
new file mode 100644
index 000000000000..8d2706075360
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -0,0 +1,149 @@
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
10int 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}
31EXPORT_SYMBOL(flexcop_dma_allocate);
32
33void 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}
38EXPORT_SYMBOL(flexcop_dma_free);
39
40int 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}
53EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
54
55int 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}
68EXPORT_SYMBOL(flexcop_dma_control_size_irq);
69
70int 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}
83EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
84
85int 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}
113EXPORT_SYMBOL(flexcop_dma_config);
114
115static 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 */
125int 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}
136EXPORT_SYMBOL(flexcop_dma_config_timer);
137
138int 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}
149EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
new file mode 100644
index 000000000000..4dbedd819734
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c
@@ -0,0 +1,157 @@
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) */
12static 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
17static 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
33static 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
51static 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
66static 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
97static 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
104static 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
113static 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
123static 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 */
137int 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}
157EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
new file mode 100644
index 000000000000..b3dd16fb5bbd
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -0,0 +1,403 @@
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
18static 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
44static 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
58static 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
88static 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
96static 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
109static 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
134static 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
139static 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 */
145static 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
166static 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
187static 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
232static 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 */
247static 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
266static 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
287static 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
294static 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
300static struct nxt2002_config samsung_tbmv_config = {
301 .demod_address = 0x0a,
302 .request_firmware = nxt2002_request_firmware,
303};
304
305static 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
327static struct mt312_config skystar23_samsung_tbdu18132_config = {
328
329 .demod_address = 0x0e,
330 .pll_set = skystar23_samsung_tbdu18132_pll_set,
331};
332
333static 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 */
340int 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
397void 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}
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
new file mode 100644
index 000000000000..db983d704ff7
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
@@ -0,0 +1,198 @@
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
10static 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
15void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
16{
17 flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
18}
19
20void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
21{
22 flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
23}
24
25void 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
41void 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
46static 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
55static 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
75static 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
80static 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
85static 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
90static 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
95static 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
100static 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
105static 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
136int 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
185void 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}
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
new file mode 100644
index 000000000000..736251f393c2
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -0,0 +1,204 @@
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
12static 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
45static 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
68static 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 */
90static 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
126int 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 */
161EXPORT_SYMBOL(flexcop_i2c_request);
162
163static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
164{
165 return I2C_FUNC_I2C;
166}
167
168static 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
175int 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
198void 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}
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
new file mode 100644
index 000000000000..19e06da46774
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -0,0 +1,66 @@
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
10void 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
39const char *flexcop_revision_names[] = {
40 "Unkown chip",
41 "FlexCopII",
42 "FlexCopIIb",
43 "FlexCopIII",
44};
45
46const 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
55const char *flexcop_bus_names[] = {
56 "USB",
57 "PCI",
58};
59
60void 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}
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
new file mode 100644
index 000000000000..693af41f3370
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -0,0 +1,365 @@
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
12static int enable_pid_filtering = 0;
13module_param(enable_pid_filtering, int, 0444);
14MODULE_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
30static int debug = 0;
31module_param(debug, int, 0644);
32MODULE_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
38struct 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
59static int lastwreg,lastwval,lastrreg,lastrval;
60
61static 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
75static 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 */
91static 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
147static 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
180static 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;
194dma1_free:
195 flexcop_dma_free(&fc_pci->dma[0]);
196
197success:
198 return ret;
199}
200
201static 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
210static 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
246err_pci_iounmap:
247 pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
248 pci_set_drvdata(fc_pci->pdev, NULL);
249err_pci_release_regions:
250 pci_release_regions(fc_pci->pdev);
251err_pci_disable_device:
252 pci_disable_device(fc_pci->pdev);
253
254success:
255 return ret;
256}
257
258static 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
271static 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;
312err_fc_exit:
313 flexcop_device_exit(fc);
314err_pci_exit:
315 flexcop_pci_exit(fc_pci);
316err_kfree:
317 flexcop_device_kfree(fc);
318success:
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 */
325static 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
335static struct pci_device_id flexcop_pci_tbl[] = {
336 { PCI_DEVICE(0x13d0, 0x2103) },
337/* { PCI_DEVICE(0x13d0, 0x2200) }, PCI FlexCopIII ? */
338 { },
339};
340
341MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl);
342
343static 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
350static int __init flexcop_pci_module_init(void)
351{
352 return pci_register_driver(&flexcop_pci_driver);
353}
354
355static void __exit flexcop_pci_module_exit(void)
356{
357 pci_unregister_driver(&flexcop_pci_driver);
358}
359
360module_init(flexcop_pci_module_init);
361module_exit(flexcop_pci_module_exit);
362
363MODULE_AUTHOR(DRIVER_AUTHOR);
364MODULE_DESCRIPTION(DRIVER_NAME);
365MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
new file mode 100644
index 000000000000..41835c5280ae
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -0,0 +1,700 @@
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
12typedef enum {
13 FLEXCOP_UNK = 0,
14 FLEXCOP_II,
15 FLEXCOP_IIB,
16 FLEXCOP_III,
17} flexcop_revision_t;
18
19extern const char *flexcop_revision_names[];
20
21typedef 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
30typedef enum {
31 FC_USB = 0,
32 FC_PCI,
33} flexcop_bus_t;
34
35extern const char *flexcop_device_names[];
36
37/* FlexCop IBI Registers */
38
39/* flexcop_ibi_reg - a huge union representing the register structure */
40typedef 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
588extern flexcop_ibi_value ibi_zero;
589
590typedef 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
596typedef enum {
597 FC_WRITE = 0,
598 FC_READ = 1,
599} flexcop_access_op_t;
600
601typedef 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
608typedef 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
615typedef 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
622typedef 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
629typedef enum {
630 FC_DMA_1 = 1,
631 FC_DMA_2 = 2,
632} flexcop_dma_index_t;
633
634typedef 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 */
640typedef 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
diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
new file mode 100644
index 000000000000..01570ec80962
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-sram.c
@@ -0,0 +1,403 @@
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
10static 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
15int 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
31int 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}
58EXPORT_SYMBOL(flexcop_sram_set_dest);
59
60void 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}
64EXPORT_SYMBOL(flexcop_wan_set_speed);
65
66void 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}
74EXPORT_SYMBOL(flexcop_sram_ctrl);
75
76#if 0
77static 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
102static 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
141static 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
161static 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
181static 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
203static 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
225static 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
230static 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
256static 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
304static 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
330static 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
398static void sll_detect_sram_size(struct adapter *adapter)
399{
400 sram_detect_for_flex2(adapter);
401}
402
403#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
new file mode 100644
index 000000000000..5fa68febf3a6
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -0,0 +1,530 @@
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
35static int debug;
36module_param(debug, int, 0644);
37MODULE_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 */
67static 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 */
95static 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
151static 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
181static 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
187static 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 */
213static 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 */
263static 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
271static 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
276static 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
285static 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
311static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff)
312{
313 /* submit/kill iso packets */
314 return 0;
315}
316
317static 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
331static 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;
392urb_error:
393 flexcop_usb_transfer_exit(fc_usb);
394success:
395 return ret;
396}
397
398static 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
422static void flexcop_usb_exit(struct flexcop_usb *fc_usb)
423{
424 usb_set_intfdata(fc_usb->uintf, NULL);
425}
426
427static 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;
473err_fc_exit:
474 flexcop_device_exit(fc);
475err_usb_exit:
476 flexcop_usb_exit(fc_usb);
477err_kfree:
478 flexcop_device_kfree(fc);
479success:
480 return ret;
481}
482
483static 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
493static 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 */
499static 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 */
508static 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
519static void __exit flexcop_usb_module_exit(void)
520{
521 /* deregister this driver from the USB subsystem */
522 usb_deregister(&flexcop_usb_driver);
523}
524
525module_init(flexcop_usb_module_init);
526module_exit(flexcop_usb_module_exit);
527
528MODULE_AUTHOR(DRIVER_AUTHOR);
529MODULE_DESCRIPTION(DRIVER_NAME);
530MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/dvb/b2c2/flexcop-usb.h
new file mode 100644
index 000000000000..bfcec25ff2d9
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-usb.h
@@ -0,0 +1,116 @@
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
14struct 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?*/
28typedef 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 */
42typedef 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 */
55typedef 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 */
71typedef 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
100typedef 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
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
new file mode 100644
index 000000000000..1998267207fb
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -0,0 +1,288 @@
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
47int b2c2_flexcop_debug;
48module_param_named(debug, b2c2_flexcop_debug, int, 0644);
49MODULE_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 */
53flexcop_ibi_value ibi_zero;
54
55static 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
61static 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
67static 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
121err_connect_frontend:
122 fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
123err_dmx_add_mem_frontend:
124 fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
125err_dmx_add_hw_frontend:
126 dvb_dmxdev_release(&fc->dmxdev);
127err_dmx_dev:
128 dvb_dmx_release(&fc->demux);
129err_dmx:
130 dvb_unregister_adapter(&fc->dvb_adapter);
131 return ret;
132
133success:
134 return 0;
135}
136
137static 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 */
156void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len)
157{
158 dvb_dmx_swfilter(&fc->demux, buf, len);
159}
160EXPORT_SYMBOL(flexcop_pass_dmx_data);
161
162void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no)
163{
164 dvb_dmx_swfilter_packets(&fc->demux, buf, no);
165}
166EXPORT_SYMBOL(flexcop_pass_dmx_packets);
167
168static 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
193struct 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}
215EXPORT_SYMBOL(flexcop_device_kmalloc);
216
217void flexcop_device_kfree(struct flexcop_device *fc)
218{
219 kfree(fc->bus_specific);
220 kfree(fc);
221}
222EXPORT_SYMBOL(flexcop_device_kfree);
223
224int 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;
257error:
258 flexcop_device_exit(fc);
259success:
260 return ret;
261}
262EXPORT_SYMBOL(flexcop_device_initialize);
263
264void flexcop_device_exit(struct flexcop_device *fc)
265{
266 flexcop_frontend_exit(fc);
267 flexcop_i2c_exit(fc);
268 flexcop_dvb_exit(fc);
269}
270EXPORT_SYMBOL(flexcop_device_exit);
271
272static int flexcop_module_init(void)
273{
274 info(DRIVER_NAME " loaded successfully");
275 return 0;
276}
277
278static void flexcop_module_cleanup(void)
279{
280 info(DRIVER_NAME " unloaded successfully");
281}
282
283module_init(flexcop_module_init);
284module_exit(flexcop_module_cleanup);
285
286MODULE_AUTHOR(DRIVER_AUTHOR);
287MODULE_DESCRIPTION(DRIVER_NAME);
288MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/dvb/b2c2/flexcop.h
new file mode 100644
index 000000000000..caa343a97bdc
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop.h
@@ -0,0 +1,30 @@
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
14extern 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