diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/media/common | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/media/common')
35 files changed, 14 insertions, 12288 deletions
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index d2a436ce77f..769c6f8142d 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig | |||
@@ -1,10 +1,9 @@ | |||
1 | # Used by common drivers, when they need to ask questions | 1 | config VIDEO_SAA7146 |
2 | config MEDIA_COMMON_OPTIONS | 2 | tristate |
3 | bool | 3 | depends on I2C && PCI |
4 | 4 | ||
5 | comment "common driver options" | 5 | config VIDEO_SAA7146_VV |
6 | depends on MEDIA_COMMON_OPTIONS | 6 | tristate |
7 | 7 | depends on VIDEO_V4L2 | |
8 | source "drivers/media/common/b2c2/Kconfig" | 8 | select VIDEOBUF_DMA_SG |
9 | source "drivers/media/common/saa7146/Kconfig" | 9 | select VIDEO_SAA7146 |
10 | source "drivers/media/common/siano/Kconfig" | ||
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index b8e2e3a33a3..e3ec9639321 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile | |||
@@ -1 +1,6 @@ | |||
1 | obj-y += b2c2/ saa7146/ siano/ | 1 | saa7146-objs := saa7146_i2c.o saa7146_core.o |
2 | saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o | ||
3 | |||
4 | obj-y += tuners/ | ||
5 | obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o | ||
6 | obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o | ||
diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig deleted file mode 100644 index a8c6cdfaa2f..00000000000 --- a/drivers/media/common/b2c2/Kconfig +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | config DVB_B2C2_FLEXCOP | ||
2 | tristate | ||
3 | depends on DVB_CORE && I2C | ||
4 | depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB | ||
5 | default y | ||
6 | select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT | ||
7 | select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT | ||
8 | select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT | ||
9 | select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT | ||
10 | select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT | ||
11 | select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT | ||
12 | select DVB_BCM3510 if MEDIA_SUBDRV_AUTOSELECT | ||
13 | select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT | ||
14 | select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT | ||
15 | select DVB_TUNER_ITD1000 if MEDIA_SUBDRV_AUTOSELECT | ||
16 | select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT | ||
17 | select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT | ||
18 | select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT | ||
19 | select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT | ||
20 | |||
21 | # Selected via the PCI or USB flexcop drivers | ||
22 | config DVB_B2C2_FLEXCOP_DEBUG | ||
23 | bool | ||
diff --git a/drivers/media/common/b2c2/Makefile b/drivers/media/common/b2c2/Makefile deleted file mode 100644 index 24993a5b38b..00000000000 --- a/drivers/media/common/b2c2/Makefile +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | b2c2-flexcop-objs += flexcop.o flexcop-fe-tuner.o flexcop-i2c.o | ||
2 | b2c2-flexcop-objs += flexcop-sram.o flexcop-eeprom.o flexcop-misc.o | ||
3 | b2c2-flexcop-objs += flexcop-hw-filter.o | ||
4 | obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o | ||
5 | |||
6 | ccflags-y += -Idrivers/media/dvb-core/ | ||
7 | ccflags-y += -Idrivers/media/dvb-frontends/ | ||
8 | ccflags-y += -Idrivers/media/tuners/ | ||
diff --git a/drivers/media/common/b2c2/flexcop-common.h b/drivers/media/common/b2c2/flexcop-common.h deleted file mode 100644 index 437912e4982..00000000000 --- a/drivers/media/common/b2c2/flexcop-common.h +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-common.h - common header file for device-specific source files | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #ifndef __FLEXCOP_COMMON_H__ | ||
7 | #define __FLEXCOP_COMMON_H__ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/mutex.h> | ||
12 | |||
13 | #include "flexcop-reg.h" | ||
14 | |||
15 | #include "dmxdev.h" | ||
16 | #include "dvb_demux.h" | ||
17 | #include "dvb_filter.h" | ||
18 | #include "dvb_net.h" | ||
19 | #include "dvb_frontend.h" | ||
20 | |||
21 | #define FC_MAX_FEED 256 | ||
22 | |||
23 | #ifndef FC_LOG_PREFIX | ||
24 | #warning please define a log prefix for your file, using a default one | ||
25 | #define FC_LOG_PREFIX "b2c2-undef" | ||
26 | #endif | ||
27 | |||
28 | /* Steal from usb.h */ | ||
29 | #undef err | ||
30 | #define err(format, arg...) \ | ||
31 | printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg) | ||
32 | #undef info | ||
33 | #define info(format, arg...) \ | ||
34 | printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg) | ||
35 | #undef warn | ||
36 | #define warn(format, arg...) \ | ||
37 | printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg) | ||
38 | |||
39 | struct flexcop_dma { | ||
40 | struct pci_dev *pdev; | ||
41 | |||
42 | u8 *cpu_addr0; | ||
43 | dma_addr_t dma_addr0; | ||
44 | u8 *cpu_addr1; | ||
45 | dma_addr_t dma_addr1; | ||
46 | u32 size; /* size of each address in bytes */ | ||
47 | }; | ||
48 | |||
49 | struct flexcop_i2c_adapter { | ||
50 | struct flexcop_device *fc; | ||
51 | struct i2c_adapter i2c_adap; | ||
52 | |||
53 | u8 no_base_addr; | ||
54 | flexcop_i2c_port_t port; | ||
55 | }; | ||
56 | |||
57 | /* Control structure for data definitions that are common to | ||
58 | * the B2C2-based PCI and USB devices. | ||
59 | */ | ||
60 | struct flexcop_device { | ||
61 | /* general */ | ||
62 | struct device *dev; /* for firmware_class */ | ||
63 | |||
64 | #define FC_STATE_DVB_INIT 0x01 | ||
65 | #define FC_STATE_I2C_INIT 0x02 | ||
66 | #define FC_STATE_FE_INIT 0x04 | ||
67 | int init_state; | ||
68 | |||
69 | /* device information */ | ||
70 | int has_32_hw_pid_filter; | ||
71 | flexcop_revision_t rev; | ||
72 | flexcop_device_type_t dev_type; | ||
73 | flexcop_bus_t bus_type; | ||
74 | |||
75 | /* dvb stuff */ | ||
76 | struct dvb_adapter dvb_adapter; | ||
77 | struct dvb_frontend *fe; | ||
78 | struct dvb_net dvbnet; | ||
79 | struct dvb_demux demux; | ||
80 | struct dmxdev dmxdev; | ||
81 | struct dmx_frontend hw_frontend; | ||
82 | struct dmx_frontend mem_frontend; | ||
83 | int (*fe_sleep) (struct dvb_frontend *); | ||
84 | |||
85 | struct flexcop_i2c_adapter fc_i2c_adap[3]; | ||
86 | struct mutex i2c_mutex; | ||
87 | struct module *owner; | ||
88 | |||
89 | /* options and status */ | ||
90 | int extra_feedcount; | ||
91 | int feedcount; | ||
92 | int pid_filtering; | ||
93 | int fullts_streaming_state; | ||
94 | |||
95 | /* bus specific callbacks */ | ||
96 | flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, | ||
97 | flexcop_ibi_register); | ||
98 | int (*write_ibi_reg) (struct flexcop_device *, | ||
99 | flexcop_ibi_register, flexcop_ibi_value); | ||
100 | int (*i2c_request) (struct flexcop_i2c_adapter *, | ||
101 | flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); | ||
102 | int (*stream_control) (struct flexcop_device *, int); | ||
103 | int (*get_mac_addr) (struct flexcop_device *fc, int extended); | ||
104 | void *bus_specific; | ||
105 | }; | ||
106 | |||
107 | /* exported prototypes */ | ||
108 | |||
109 | /* from flexcop.c */ | ||
110 | void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len); | ||
111 | void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no); | ||
112 | |||
113 | struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len); | ||
114 | void flexcop_device_kfree(struct flexcop_device *); | ||
115 | |||
116 | int flexcop_device_initialize(struct flexcop_device *); | ||
117 | void flexcop_device_exit(struct flexcop_device *fc); | ||
118 | void flexcop_reset_block_300(struct flexcop_device *fc); | ||
119 | |||
120 | /* from flexcop-dma.c */ | ||
121 | int flexcop_dma_allocate(struct pci_dev *pdev, | ||
122 | struct flexcop_dma *dma, u32 size); | ||
123 | void flexcop_dma_free(struct flexcop_dma *dma); | ||
124 | |||
125 | int flexcop_dma_control_timer_irq(struct flexcop_device *fc, | ||
126 | flexcop_dma_index_t no, int onoff); | ||
127 | int flexcop_dma_control_size_irq(struct flexcop_device *fc, | ||
128 | flexcop_dma_index_t no, int onoff); | ||
129 | int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, | ||
130 | flexcop_dma_index_t dma_idx); | ||
131 | int flexcop_dma_xfer_control(struct flexcop_device *fc, | ||
132 | flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, | ||
133 | int onoff); | ||
134 | int flexcop_dma_config_timer(struct flexcop_device *fc, | ||
135 | flexcop_dma_index_t dma_idx, u8 cycles); | ||
136 | |||
137 | /* from flexcop-eeprom.c */ | ||
138 | /* the PCI part uses this call to get the MAC address, the USB part has its own */ | ||
139 | int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended); | ||
140 | |||
141 | /* from flexcop-i2c.c */ | ||
142 | /* the PCI part uses this a i2c_request callback, whereas the usb part has its own | ||
143 | * one. We have it in flexcop-i2c.c, because it is going via the actual | ||
144 | * I2C-channel of the flexcop. | ||
145 | */ | ||
146 | int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t, | ||
147 | u8 chipaddr, u8 addr, u8 *buf, u16 len); | ||
148 | |||
149 | /* from flexcop-sram.c */ | ||
150 | int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, | ||
151 | flexcop_sram_dest_target_t target); | ||
152 | void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s); | ||
153 | void flexcop_sram_ctrl(struct flexcop_device *fc, | ||
154 | int usb_wan, int sramdma, int maximumfill); | ||
155 | |||
156 | /* global prototypes for the flexcop-chip */ | ||
157 | /* from flexcop-fe-tuner.c */ | ||
158 | int flexcop_frontend_init(struct flexcop_device *fc); | ||
159 | void flexcop_frontend_exit(struct flexcop_device *fc); | ||
160 | |||
161 | /* from flexcop-i2c.c */ | ||
162 | int flexcop_i2c_init(struct flexcop_device *fc); | ||
163 | void flexcop_i2c_exit(struct flexcop_device *fc); | ||
164 | |||
165 | /* from flexcop-sram.c */ | ||
166 | int flexcop_sram_init(struct flexcop_device *fc); | ||
167 | |||
168 | /* from flexcop-misc.c */ | ||
169 | void flexcop_determine_revision(struct flexcop_device *fc); | ||
170 | void flexcop_device_name(struct flexcop_device *fc, | ||
171 | const char *prefix, const char *suffix); | ||
172 | void flexcop_dump_reg(struct flexcop_device *fc, | ||
173 | flexcop_ibi_register reg, int num); | ||
174 | |||
175 | /* from flexcop-hw-filter.c */ | ||
176 | int flexcop_pid_feed_control(struct flexcop_device *fc, | ||
177 | struct dvb_demux_feed *dvbdmxfeed, int onoff); | ||
178 | void flexcop_hw_filter_init(struct flexcop_device *fc); | ||
179 | |||
180 | void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); | ||
181 | |||
182 | void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); | ||
183 | void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff); | ||
184 | |||
185 | #endif | ||
diff --git a/drivers/media/common/b2c2/flexcop-eeprom.c b/drivers/media/common/b2c2/flexcop-eeprom.c deleted file mode 100644 index a25373a9bd8..00000000000 --- a/drivers/media/common/b2c2/flexcop-eeprom.c +++ /dev/null | |||
@@ -1,147 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading) | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #include "flexcop.h" | ||
7 | |||
8 | #if 0 | ||
9 | /*EEPROM (Skystar2 has one "24LC08B" chip on board) */ | ||
10 | static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len) | ||
11 | { | ||
12 | return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len); | ||
13 | } | ||
14 | |||
15 | static int eeprom_lrc_write(struct adapter *adapter, u32 addr, | ||
16 | u32 len, u8 *wbuf, u8 *rbuf, int retries) | ||
17 | { | ||
18 | int i; | ||
19 | |||
20 | for (i = 0; i < retries; i++) { | ||
21 | if (eeprom_write(adapter, addr, wbuf, len) == len) { | ||
22 | if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1) | ||
23 | return 1; | ||
24 | } | ||
25 | } | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | /* These functions could be used to unlock SkyStar2 cards. */ | ||
30 | |||
31 | static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len) | ||
32 | { | ||
33 | u8 rbuf[20]; | ||
34 | u8 wbuf[20]; | ||
35 | |||
36 | if (len != 16) | ||
37 | return 0; | ||
38 | |||
39 | memcpy(wbuf, key, len); | ||
40 | wbuf[16] = 0; | ||
41 | wbuf[17] = 0; | ||
42 | wbuf[18] = 0; | ||
43 | wbuf[19] = calc_lrc(wbuf, 19); | ||
44 | return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4); | ||
45 | } | ||
46 | |||
47 | static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len) | ||
48 | { | ||
49 | u8 buf[20]; | ||
50 | |||
51 | if (len != 16) | ||
52 | return 0; | ||
53 | |||
54 | if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0) | ||
55 | return 0; | ||
56 | |||
57 | memcpy(key, buf, len); | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac) | ||
62 | { | ||
63 | u8 tmp[8]; | ||
64 | |||
65 | if (type != 0) { | ||
66 | tmp[0] = mac[0]; | ||
67 | tmp[1] = mac[1]; | ||
68 | tmp[2] = mac[2]; | ||
69 | tmp[3] = mac[5]; | ||
70 | tmp[4] = mac[6]; | ||
71 | tmp[5] = mac[7]; | ||
72 | } else { | ||
73 | tmp[0] = mac[0]; | ||
74 | tmp[1] = mac[1]; | ||
75 | tmp[2] = mac[2]; | ||
76 | tmp[3] = mac[3]; | ||
77 | tmp[4] = mac[4]; | ||
78 | tmp[5] = mac[5]; | ||
79 | } | ||
80 | |||
81 | tmp[6] = 0; | ||
82 | tmp[7] = calc_lrc(tmp, 7); | ||
83 | |||
84 | if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8) | ||
85 | return 1; | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int flexcop_eeprom_read(struct flexcop_device *fc, | ||
90 | u16 addr, u8 *buf, u16 len) | ||
91 | { | ||
92 | return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len); | ||
93 | } | ||
94 | |||
95 | #endif | ||
96 | |||
97 | static u8 calc_lrc(u8 *buf, int len) | ||
98 | { | ||
99 | int i; | ||
100 | u8 sum = 0; | ||
101 | for (i = 0; i < len; i++) | ||
102 | sum = sum ^ buf[i]; | ||
103 | return sum; | ||
104 | } | ||
105 | |||
106 | static int flexcop_eeprom_request(struct flexcop_device *fc, | ||
107 | flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) | ||
108 | { | ||
109 | int i,ret = 0; | ||
110 | u8 chipaddr = 0x50 | ((addr >> 8) & 3); | ||
111 | for (i = 0; i < retries; i++) { | ||
112 | ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr, | ||
113 | addr & 0xff, buf, len); | ||
114 | if (ret == 0) | ||
115 | break; | ||
116 | } | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, | ||
121 | u8 *buf, u16 len, int retries) | ||
122 | { | ||
123 | int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries); | ||
124 | if (ret == 0) | ||
125 | if (calc_lrc(buf, len - 1) != buf[len - 1]) | ||
126 | ret = -EINVAL; | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | /* JJ's comment about extended == 1: it is not presently used anywhere but was | ||
131 | * added to the low-level functions for possible support of EUI64 */ | ||
132 | int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) | ||
133 | { | ||
134 | u8 buf[8]; | ||
135 | int ret = 0; | ||
136 | |||
137 | if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) { | ||
138 | if (extended != 0) { | ||
139 | err("TODO: extended (EUI64) MAC addresses aren't " | ||
140 | "completely supported yet"); | ||
141 | ret = -EINVAL; | ||
142 | } else | ||
143 | memcpy(fc->dvb_adapter.proposed_mac,buf,6); | ||
144 | } | ||
145 | return ret; | ||
146 | } | ||
147 | EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr); | ||
diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c deleted file mode 100644 index 850a6c60675..00000000000 --- a/drivers/media/common/b2c2/flexcop-fe-tuner.c +++ /dev/null | |||
@@ -1,678 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #include <media/tuner.h> | ||
7 | #include "flexcop.h" | ||
8 | #include "mt312.h" | ||
9 | #include "stv0299.h" | ||
10 | #include "s5h1420.h" | ||
11 | #include "itd1000.h" | ||
12 | #include "cx24113.h" | ||
13 | #include "cx24123.h" | ||
14 | #include "isl6421.h" | ||
15 | #include "mt352.h" | ||
16 | #include "bcm3510.h" | ||
17 | #include "nxt200x.h" | ||
18 | #include "dvb-pll.h" | ||
19 | #include "lgdt330x.h" | ||
20 | #include "tuner-simple.h" | ||
21 | #include "stv0297.h" | ||
22 | |||
23 | |||
24 | /* Can we use the specified front-end? Remember that if we are compiled | ||
25 | * into the kernel we can't call code that's in modules. */ | ||
26 | #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ | ||
27 | (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) | ||
28 | |||
29 | /* lnb control */ | ||
30 | #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) | ||
31 | static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
32 | { | ||
33 | struct flexcop_device *fc = fe->dvb->priv; | ||
34 | flexcop_ibi_value v; | ||
35 | deb_tuner("polarity/voltage = %u\n", voltage); | ||
36 | |||
37 | v = fc->read_ibi_reg(fc, misc_204); | ||
38 | switch (voltage) { | ||
39 | case SEC_VOLTAGE_OFF: | ||
40 | v.misc_204.ACPI1_sig = 1; | ||
41 | break; | ||
42 | case SEC_VOLTAGE_13: | ||
43 | v.misc_204.ACPI1_sig = 0; | ||
44 | v.misc_204.LNB_L_H_sig = 0; | ||
45 | break; | ||
46 | case SEC_VOLTAGE_18: | ||
47 | v.misc_204.ACPI1_sig = 0; | ||
48 | v.misc_204.LNB_L_H_sig = 1; | ||
49 | break; | ||
50 | default: | ||
51 | err("unknown SEC_VOLTAGE value"); | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | return fc->write_ibi_reg(fc, misc_204, v); | ||
55 | } | ||
56 | #endif | ||
57 | |||
58 | #if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312) | ||
59 | static int flexcop_sleep(struct dvb_frontend* fe) | ||
60 | { | ||
61 | struct flexcop_device *fc = fe->dvb->priv; | ||
62 | if (fc->fe_sleep) | ||
63 | return fc->fe_sleep(fe); | ||
64 | return 0; | ||
65 | } | ||
66 | #endif | ||
67 | |||
68 | /* SkyStar2 DVB-S rev 2.3 */ | ||
69 | #if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL) | ||
70 | static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
71 | { | ||
72 | /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ | ||
73 | struct flexcop_device *fc = fe->dvb->priv; | ||
74 | flexcop_ibi_value v; | ||
75 | u16 ax; | ||
76 | v.raw = 0; | ||
77 | deb_tuner("tone = %u\n",tone); | ||
78 | |||
79 | switch (tone) { | ||
80 | case SEC_TONE_ON: | ||
81 | ax = 0x01ff; | ||
82 | break; | ||
83 | case SEC_TONE_OFF: | ||
84 | ax = 0; | ||
85 | break; | ||
86 | default: | ||
87 | err("unknown SEC_TONE value"); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */ | ||
92 | v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax; | ||
93 | v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax; | ||
94 | return fc->write_ibi_reg(fc,lnb_switch_freq_200,v); | ||
95 | } | ||
96 | |||
97 | static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data) | ||
98 | { | ||
99 | flexcop_set_tone(fe, SEC_TONE_ON); | ||
100 | udelay(data ? 500 : 1000); | ||
101 | flexcop_set_tone(fe, SEC_TONE_OFF); | ||
102 | udelay(data ? 1000 : 500); | ||
103 | } | ||
104 | |||
105 | static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data) | ||
106 | { | ||
107 | int i, par = 1, d; | ||
108 | for (i = 7; i >= 0; i--) { | ||
109 | d = (data >> i) & 1; | ||
110 | par ^= d; | ||
111 | flexcop_diseqc_send_bit(fe, d); | ||
112 | } | ||
113 | flexcop_diseqc_send_bit(fe, par); | ||
114 | } | ||
115 | |||
116 | static int flexcop_send_diseqc_msg(struct dvb_frontend *fe, | ||
117 | int len, u8 *msg, unsigned long burst) | ||
118 | { | ||
119 | int i; | ||
120 | |||
121 | flexcop_set_tone(fe, SEC_TONE_OFF); | ||
122 | mdelay(16); | ||
123 | |||
124 | for (i = 0; i < len; i++) | ||
125 | flexcop_diseqc_send_byte(fe,msg[i]); | ||
126 | mdelay(16); | ||
127 | |||
128 | if (burst != -1) { | ||
129 | if (burst) | ||
130 | flexcop_diseqc_send_byte(fe, 0xff); | ||
131 | else { | ||
132 | flexcop_set_tone(fe, SEC_TONE_ON); | ||
133 | mdelay(12); | ||
134 | udelay(500); | ||
135 | flexcop_set_tone(fe, SEC_TONE_OFF); | ||
136 | } | ||
137 | msleep(20); | ||
138 | } | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||
143 | struct dvb_diseqc_master_cmd *cmd) | ||
144 | { | ||
145 | return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0); | ||
146 | } | ||
147 | |||
148 | static int flexcop_diseqc_send_burst(struct dvb_frontend *fe, | ||
149 | fe_sec_mini_cmd_t minicmd) | ||
150 | { | ||
151 | return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd); | ||
152 | } | ||
153 | |||
154 | static struct mt312_config skystar23_samsung_tbdu18132_config = { | ||
155 | .demod_address = 0x0e, | ||
156 | }; | ||
157 | |||
158 | static int skystar2_rev23_attach(struct flexcop_device *fc, | ||
159 | struct i2c_adapter *i2c) | ||
160 | { | ||
161 | struct dvb_frontend_ops *ops; | ||
162 | |||
163 | fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c); | ||
164 | if (!fc->fe) | ||
165 | return 0; | ||
166 | |||
167 | if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c, | ||
168 | DVB_PLL_SAMSUNG_TBDU18132)) | ||
169 | return 0; | ||
170 | |||
171 | ops = &fc->fe->ops; | ||
172 | ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; | ||
173 | ops->diseqc_send_burst = flexcop_diseqc_send_burst; | ||
174 | ops->set_tone = flexcop_set_tone; | ||
175 | ops->set_voltage = flexcop_set_voltage; | ||
176 | fc->fe_sleep = ops->sleep; | ||
177 | ops->sleep = flexcop_sleep; | ||
178 | return 1; | ||
179 | } | ||
180 | #else | ||
181 | #define skystar2_rev23_attach NULL | ||
182 | #endif | ||
183 | |||
184 | /* SkyStar2 DVB-S rev 2.6 */ | ||
185 | #if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL) | ||
186 | static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, | ||
187 | u32 srate, u32 ratio) | ||
188 | { | ||
189 | u8 aclk = 0; | ||
190 | u8 bclk = 0; | ||
191 | |||
192 | if (srate < 1500000) { | ||
193 | aclk = 0xb7; bclk = 0x47; | ||
194 | } else if (srate < 3000000) { | ||
195 | aclk = 0xb7; bclk = 0x4b; | ||
196 | } else if (srate < 7000000) { | ||
197 | aclk = 0xb7; bclk = 0x4f; | ||
198 | } else if (srate < 14000000) { | ||
199 | aclk = 0xb7; bclk = 0x53; | ||
200 | } else if (srate < 30000000) { | ||
201 | aclk = 0xb6; bclk = 0x53; | ||
202 | } else if (srate < 45000000) { | ||
203 | aclk = 0xb4; bclk = 0x51; | ||
204 | } | ||
205 | |||
206 | stv0299_writereg(fe, 0x13, aclk); | ||
207 | stv0299_writereg(fe, 0x14, bclk); | ||
208 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
209 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
210 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static u8 samsung_tbmu24112_inittab[] = { | ||
215 | 0x01, 0x15, | ||
216 | 0x02, 0x30, | ||
217 | 0x03, 0x00, | ||
218 | 0x04, 0x7D, | ||
219 | 0x05, 0x35, | ||
220 | 0x06, 0x02, | ||
221 | 0x07, 0x00, | ||
222 | 0x08, 0xC3, | ||
223 | 0x0C, 0x00, | ||
224 | 0x0D, 0x81, | ||
225 | 0x0E, 0x23, | ||
226 | 0x0F, 0x12, | ||
227 | 0x10, 0x7E, | ||
228 | 0x11, 0x84, | ||
229 | 0x12, 0xB9, | ||
230 | 0x13, 0x88, | ||
231 | 0x14, 0x89, | ||
232 | 0x15, 0xC9, | ||
233 | 0x16, 0x00, | ||
234 | 0x17, 0x5C, | ||
235 | 0x18, 0x00, | ||
236 | 0x19, 0x00, | ||
237 | 0x1A, 0x00, | ||
238 | 0x1C, 0x00, | ||
239 | 0x1D, 0x00, | ||
240 | 0x1E, 0x00, | ||
241 | 0x1F, 0x3A, | ||
242 | 0x20, 0x2E, | ||
243 | 0x21, 0x80, | ||
244 | 0x22, 0xFF, | ||
245 | 0x23, 0xC1, | ||
246 | 0x28, 0x00, | ||
247 | 0x29, 0x1E, | ||
248 | 0x2A, 0x14, | ||
249 | 0x2B, 0x0F, | ||
250 | 0x2C, 0x09, | ||
251 | 0x2D, 0x05, | ||
252 | 0x31, 0x1F, | ||
253 | 0x32, 0x19, | ||
254 | 0x33, 0xFE, | ||
255 | 0x34, 0x93, | ||
256 | 0xff, 0xff, | ||
257 | }; | ||
258 | |||
259 | static struct stv0299_config samsung_tbmu24112_config = { | ||
260 | .demod_address = 0x68, | ||
261 | .inittab = samsung_tbmu24112_inittab, | ||
262 | .mclk = 88000000UL, | ||
263 | .invert = 0, | ||
264 | .skip_reinit = 0, | ||
265 | .lock_output = STV0299_LOCKOUTPUT_LK, | ||
266 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
267 | .min_delay_ms = 100, | ||
268 | .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, | ||
269 | }; | ||
270 | |||
271 | static int skystar2_rev26_attach(struct flexcop_device *fc, | ||
272 | struct i2c_adapter *i2c) | ||
273 | { | ||
274 | fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); | ||
275 | if (!fc->fe) | ||
276 | return 0; | ||
277 | |||
278 | if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c, | ||
279 | DVB_PLL_SAMSUNG_TBMU24112)) | ||
280 | return 0; | ||
281 | |||
282 | fc->fe->ops.set_voltage = flexcop_set_voltage; | ||
283 | fc->fe_sleep = fc->fe->ops.sleep; | ||
284 | fc->fe->ops.sleep = flexcop_sleep; | ||
285 | return 1; | ||
286 | |||
287 | } | ||
288 | #else | ||
289 | #define skystar2_rev26_attach NULL | ||
290 | #endif | ||
291 | |||
292 | /* SkyStar2 DVB-S rev 2.7 */ | ||
293 | #if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000) | ||
294 | static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { | ||
295 | .demod_address = 0x53, | ||
296 | .invert = 1, | ||
297 | .repeated_start_workaround = 1, | ||
298 | .serial_mpeg = 1, | ||
299 | }; | ||
300 | |||
301 | static struct itd1000_config skystar2_rev2_7_itd1000_config = { | ||
302 | .i2c_address = 0x61, | ||
303 | }; | ||
304 | |||
305 | static int skystar2_rev27_attach(struct flexcop_device *fc, | ||
306 | struct i2c_adapter *i2c) | ||
307 | { | ||
308 | flexcop_ibi_value r108; | ||
309 | struct i2c_adapter *i2c_tuner; | ||
310 | |||
311 | /* enable no_base_addr - no repeated start when reading */ | ||
312 | fc->fc_i2c_adap[0].no_base_addr = 1; | ||
313 | fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, | ||
314 | i2c); | ||
315 | if (!fc->fe) | ||
316 | goto fail; | ||
317 | |||
318 | i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe); | ||
319 | if (!i2c_tuner) | ||
320 | goto fail; | ||
321 | |||
322 | fc->fe_sleep = fc->fe->ops.sleep; | ||
323 | fc->fe->ops.sleep = flexcop_sleep; | ||
324 | |||
325 | /* enable no_base_addr - no repeated start when reading */ | ||
326 | fc->fc_i2c_adap[2].no_base_addr = 1; | ||
327 | if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, | ||
328 | 0x08, 1, 1)) { | ||
329 | err("ISL6421 could NOT be attached"); | ||
330 | goto fail_isl; | ||
331 | } | ||
332 | info("ISL6421 successfully attached"); | ||
333 | |||
334 | /* the ITD1000 requires a lower i2c clock - is it a problem ? */ | ||
335 | r108.raw = 0x00000506; | ||
336 | fc->write_ibi_reg(fc, tw_sm_c_108, r108); | ||
337 | if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner, | ||
338 | &skystar2_rev2_7_itd1000_config)) { | ||
339 | err("ITD1000 could NOT be attached"); | ||
340 | /* Should i2c clock be restored? */ | ||
341 | goto fail_isl; | ||
342 | } | ||
343 | info("ITD1000 successfully attached"); | ||
344 | |||
345 | return 1; | ||
346 | |||
347 | fail_isl: | ||
348 | fc->fc_i2c_adap[2].no_base_addr = 0; | ||
349 | fail: | ||
350 | /* for the next devices we need it again */ | ||
351 | fc->fc_i2c_adap[0].no_base_addr = 0; | ||
352 | return 0; | ||
353 | } | ||
354 | #else | ||
355 | #define skystar2_rev27_attach NULL | ||
356 | #endif | ||
357 | |||
358 | /* SkyStar2 rev 2.8 */ | ||
359 | #if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113) | ||
360 | static struct cx24123_config skystar2_rev2_8_cx24123_config = { | ||
361 | .demod_address = 0x55, | ||
362 | .dont_use_pll = 1, | ||
363 | .agc_callback = cx24113_agc_callback, | ||
364 | }; | ||
365 | |||
366 | static const struct cx24113_config skystar2_rev2_8_cx24113_config = { | ||
367 | .i2c_addr = 0x54, | ||
368 | .xtal_khz = 10111, | ||
369 | }; | ||
370 | |||
371 | static int skystar2_rev28_attach(struct flexcop_device *fc, | ||
372 | struct i2c_adapter *i2c) | ||
373 | { | ||
374 | struct i2c_adapter *i2c_tuner; | ||
375 | |||
376 | fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config, | ||
377 | i2c); | ||
378 | if (!fc->fe) | ||
379 | return 0; | ||
380 | |||
381 | i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe); | ||
382 | if (!i2c_tuner) | ||
383 | return 0; | ||
384 | |||
385 | if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config, | ||
386 | i2c_tuner)) { | ||
387 | err("CX24113 could NOT be attached"); | ||
388 | return 0; | ||
389 | } | ||
390 | info("CX24113 successfully attached"); | ||
391 | |||
392 | fc->fc_i2c_adap[2].no_base_addr = 1; | ||
393 | if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, | ||
394 | 0x08, 0, 0)) { | ||
395 | err("ISL6421 could NOT be attached"); | ||
396 | fc->fc_i2c_adap[2].no_base_addr = 0; | ||
397 | return 0; | ||
398 | } | ||
399 | info("ISL6421 successfully attached"); | ||
400 | /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an | ||
401 | * IR-receiver (PIC16F818) - but the card has no input for that ??? */ | ||
402 | return 1; | ||
403 | } | ||
404 | #else | ||
405 | #define skystar2_rev28_attach NULL | ||
406 | #endif | ||
407 | |||
408 | /* AirStar DVB-T */ | ||
409 | #if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL) | ||
410 | static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) | ||
411 | { | ||
412 | static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; | ||
413 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
414 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; | ||
415 | static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 }; | ||
416 | static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; | ||
417 | |||
418 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
419 | udelay(2000); | ||
420 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
421 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
422 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
423 | mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static struct mt352_config samsung_tdtc9251dh0_config = { | ||
428 | .demod_address = 0x0f, | ||
429 | .demod_init = samsung_tdtc9251dh0_demod_init, | ||
430 | }; | ||
431 | |||
432 | static int airstar_dvbt_attach(struct flexcop_device *fc, | ||
433 | struct i2c_adapter *i2c) | ||
434 | { | ||
435 | fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); | ||
436 | if (!fc->fe) | ||
437 | return 0; | ||
438 | |||
439 | return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, | ||
440 | DVB_PLL_SAMSUNG_TDTC9251DH0); | ||
441 | } | ||
442 | #else | ||
443 | #define airstar_dvbt_attach NULL | ||
444 | #endif | ||
445 | |||
446 | /* AirStar ATSC 1st generation */ | ||
447 | #if FE_SUPPORTED(BCM3510) | ||
448 | static int flexcop_fe_request_firmware(struct dvb_frontend *fe, | ||
449 | const struct firmware **fw, char* name) | ||
450 | { | ||
451 | struct flexcop_device *fc = fe->dvb->priv; | ||
452 | return request_firmware(fw, name, fc->dev); | ||
453 | } | ||
454 | |||
455 | static struct bcm3510_config air2pc_atsc_first_gen_config = { | ||
456 | .demod_address = 0x0f, | ||
457 | .request_firmware = flexcop_fe_request_firmware, | ||
458 | }; | ||
459 | |||
460 | static int airstar_atsc1_attach(struct flexcop_device *fc, | ||
461 | struct i2c_adapter *i2c) | ||
462 | { | ||
463 | fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c); | ||
464 | return fc->fe != NULL; | ||
465 | } | ||
466 | #else | ||
467 | #define airstar_atsc1_attach NULL | ||
468 | #endif | ||
469 | |||
470 | /* AirStar ATSC 2nd generation */ | ||
471 | #if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL) | ||
472 | static struct nxt200x_config samsung_tbmv_config = { | ||
473 | .demod_address = 0x0a, | ||
474 | }; | ||
475 | |||
476 | static int airstar_atsc2_attach(struct flexcop_device *fc, | ||
477 | struct i2c_adapter *i2c) | ||
478 | { | ||
479 | fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c); | ||
480 | if (!fc->fe) | ||
481 | return 0; | ||
482 | |||
483 | return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, | ||
484 | DVB_PLL_SAMSUNG_TBMV); | ||
485 | } | ||
486 | #else | ||
487 | #define airstar_atsc2_attach NULL | ||
488 | #endif | ||
489 | |||
490 | /* AirStar ATSC 3rd generation */ | ||
491 | #if FE_SUPPORTED(LGDT330X) | ||
492 | static struct lgdt330x_config air2pc_atsc_hd5000_config = { | ||
493 | .demod_address = 0x59, | ||
494 | .demod_chip = LGDT3303, | ||
495 | .serial_mpeg = 0x04, | ||
496 | .clock_polarity_flip = 1, | ||
497 | }; | ||
498 | |||
499 | static int airstar_atsc3_attach(struct flexcop_device *fc, | ||
500 | struct i2c_adapter *i2c) | ||
501 | { | ||
502 | fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c); | ||
503 | if (!fc->fe) | ||
504 | return 0; | ||
505 | |||
506 | return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61, | ||
507 | TUNER_LG_TDVS_H06XF); | ||
508 | } | ||
509 | #else | ||
510 | #define airstar_atsc3_attach NULL | ||
511 | #endif | ||
512 | |||
513 | /* CableStar2 DVB-C */ | ||
514 | #if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL) | ||
515 | static u8 alps_tdee4_stv0297_inittab[] = { | ||
516 | 0x80, 0x01, | ||
517 | 0x80, 0x00, | ||
518 | 0x81, 0x01, | ||
519 | 0x81, 0x00, | ||
520 | 0x00, 0x48, | ||
521 | 0x01, 0x58, | ||
522 | 0x03, 0x00, | ||
523 | 0x04, 0x00, | ||
524 | 0x07, 0x00, | ||
525 | 0x08, 0x00, | ||
526 | 0x30, 0xff, | ||
527 | 0x31, 0x9d, | ||
528 | 0x32, 0xff, | ||
529 | 0x33, 0x00, | ||
530 | 0x34, 0x29, | ||
531 | 0x35, 0x55, | ||
532 | 0x36, 0x80, | ||
533 | 0x37, 0x6e, | ||
534 | 0x38, 0x9c, | ||
535 | 0x40, 0x1a, | ||
536 | 0x41, 0xfe, | ||
537 | 0x42, 0x33, | ||
538 | 0x43, 0x00, | ||
539 | 0x44, 0xff, | ||
540 | 0x45, 0x00, | ||
541 | 0x46, 0x00, | ||
542 | 0x49, 0x04, | ||
543 | 0x4a, 0x51, | ||
544 | 0x4b, 0xf8, | ||
545 | 0x52, 0x30, | ||
546 | 0x53, 0x06, | ||
547 | 0x59, 0x06, | ||
548 | 0x5a, 0x5e, | ||
549 | 0x5b, 0x04, | ||
550 | 0x61, 0x49, | ||
551 | 0x62, 0x0a, | ||
552 | 0x70, 0xff, | ||
553 | 0x71, 0x04, | ||
554 | 0x72, 0x00, | ||
555 | 0x73, 0x00, | ||
556 | 0x74, 0x0c, | ||
557 | 0x80, 0x20, | ||
558 | 0x81, 0x00, | ||
559 | 0x82, 0x30, | ||
560 | 0x83, 0x00, | ||
561 | 0x84, 0x04, | ||
562 | 0x85, 0x22, | ||
563 | 0x86, 0x08, | ||
564 | 0x87, 0x1b, | ||
565 | 0x88, 0x00, | ||
566 | 0x89, 0x00, | ||
567 | 0x90, 0x00, | ||
568 | 0x91, 0x04, | ||
569 | 0xa0, 0x86, | ||
570 | 0xa1, 0x00, | ||
571 | 0xa2, 0x00, | ||
572 | 0xb0, 0x91, | ||
573 | 0xb1, 0x0b, | ||
574 | 0xc0, 0x5b, | ||
575 | 0xc1, 0x10, | ||
576 | 0xc2, 0x12, | ||
577 | 0xd0, 0x02, | ||
578 | 0xd1, 0x00, | ||
579 | 0xd2, 0x00, | ||
580 | 0xd3, 0x00, | ||
581 | 0xd4, 0x02, | ||
582 | 0xd5, 0x00, | ||
583 | 0xde, 0x00, | ||
584 | 0xdf, 0x01, | ||
585 | 0xff, 0xff, | ||
586 | }; | ||
587 | |||
588 | static struct stv0297_config alps_tdee4_stv0297_config = { | ||
589 | .demod_address = 0x1c, | ||
590 | .inittab = alps_tdee4_stv0297_inittab, | ||
591 | }; | ||
592 | |||
593 | static int cablestar2_attach(struct flexcop_device *fc, | ||
594 | struct i2c_adapter *i2c) | ||
595 | { | ||
596 | fc->fc_i2c_adap[0].no_base_addr = 1; | ||
597 | fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); | ||
598 | if (!fc->fe) | ||
599 | goto fail; | ||
600 | |||
601 | /* This tuner doesn't use the stv0297's I2C gate, but instead the | ||
602 | * tuner is connected to a different flexcop I2C adapter. */ | ||
603 | if (fc->fe->ops.i2c_gate_ctrl) | ||
604 | fc->fe->ops.i2c_gate_ctrl(fc->fe, 0); | ||
605 | fc->fe->ops.i2c_gate_ctrl = NULL; | ||
606 | |||
607 | if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, | ||
608 | &fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4)) | ||
609 | goto fail; | ||
610 | |||
611 | return 1; | ||
612 | |||
613 | fail: | ||
614 | /* Reset for next frontend to try */ | ||
615 | fc->fc_i2c_adap[0].no_base_addr = 0; | ||
616 | return 0; | ||
617 | } | ||
618 | #else | ||
619 | #define cablestar2_attach NULL | ||
620 | #endif | ||
621 | |||
622 | static struct { | ||
623 | flexcop_device_type_t type; | ||
624 | int (*attach)(struct flexcop_device *, struct i2c_adapter *); | ||
625 | } flexcop_frontends[] = { | ||
626 | { FC_SKY_REV27, skystar2_rev27_attach }, | ||
627 | { FC_SKY_REV28, skystar2_rev28_attach }, | ||
628 | { FC_SKY_REV26, skystar2_rev26_attach }, | ||
629 | { FC_AIR_DVBT, airstar_dvbt_attach }, | ||
630 | { FC_AIR_ATSC2, airstar_atsc2_attach }, | ||
631 | { FC_AIR_ATSC3, airstar_atsc3_attach }, | ||
632 | { FC_AIR_ATSC1, airstar_atsc1_attach }, | ||
633 | { FC_CABLE, cablestar2_attach }, | ||
634 | { FC_SKY_REV23, skystar2_rev23_attach }, | ||
635 | }; | ||
636 | |||
637 | /* try to figure out the frontend */ | ||
638 | int flexcop_frontend_init(struct flexcop_device *fc) | ||
639 | { | ||
640 | int i; | ||
641 | for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) { | ||
642 | if (!flexcop_frontends[i].attach) | ||
643 | continue; | ||
644 | /* type needs to be set before, because of some workarounds | ||
645 | * done based on the probed card type */ | ||
646 | fc->dev_type = flexcop_frontends[i].type; | ||
647 | if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap)) | ||
648 | goto fe_found; | ||
649 | /* Clean up partially attached frontend */ | ||
650 | if (fc->fe) { | ||
651 | dvb_frontend_detach(fc->fe); | ||
652 | fc->fe = NULL; | ||
653 | } | ||
654 | } | ||
655 | fc->dev_type = FC_UNK; | ||
656 | err("no frontend driver found for this B2C2/FlexCop adapter"); | ||
657 | return -ENODEV; | ||
658 | |||
659 | fe_found: | ||
660 | info("found '%s' .", fc->fe->ops.info.name); | ||
661 | if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { | ||
662 | err("frontend registration failed!"); | ||
663 | dvb_frontend_detach(fc->fe); | ||
664 | fc->fe = NULL; | ||
665 | return -EINVAL; | ||
666 | } | ||
667 | fc->init_state |= FC_STATE_FE_INIT; | ||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | void flexcop_frontend_exit(struct flexcop_device *fc) | ||
672 | { | ||
673 | if (fc->init_state & FC_STATE_FE_INIT) { | ||
674 | dvb_unregister_frontend(fc->fe); | ||
675 | dvb_frontend_detach(fc->fe); | ||
676 | } | ||
677 | fc->init_state &= ~FC_STATE_FE_INIT; | ||
678 | } | ||
diff --git a/drivers/media/common/b2c2/flexcop-hw-filter.c b/drivers/media/common/b2c2/flexcop-hw-filter.c deleted file mode 100644 index 77e45475f4c..00000000000 --- a/drivers/media/common/b2c2/flexcop-hw-filter.c +++ /dev/null | |||
@@ -1,232 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-hw-filter.c - pid and mac address filtering and control functions | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #include "flexcop.h" | ||
7 | |||
8 | static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) | ||
9 | { | ||
10 | flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff); | ||
11 | deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); | ||
12 | } | ||
13 | |||
14 | void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) | ||
15 | { | ||
16 | flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); | ||
17 | } | ||
18 | |||
19 | static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff) | ||
20 | { | ||
21 | flexcop_set_ibi_value(ctrl_208, Null_filter_sig, onoff); | ||
22 | } | ||
23 | |||
24 | void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]) | ||
25 | { | ||
26 | flexcop_ibi_value v418, v41c; | ||
27 | v41c = fc->read_ibi_reg(fc, mac_address_41c); | ||
28 | |||
29 | v418.mac_address_418.MAC1 = mac[0]; | ||
30 | v418.mac_address_418.MAC2 = mac[1]; | ||
31 | v418.mac_address_418.MAC3 = mac[2]; | ||
32 | v418.mac_address_418.MAC6 = mac[3]; | ||
33 | v41c.mac_address_41c.MAC7 = mac[4]; | ||
34 | v41c.mac_address_41c.MAC8 = mac[5]; | ||
35 | |||
36 | fc->write_ibi_reg(fc, mac_address_418, v418); | ||
37 | fc->write_ibi_reg(fc, mac_address_41c, v41c); | ||
38 | } | ||
39 | |||
40 | void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff) | ||
41 | { | ||
42 | flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff); | ||
43 | } | ||
44 | |||
45 | static void flexcop_pid_group_filter(struct flexcop_device *fc, | ||
46 | u16 pid, u16 mask) | ||
47 | { | ||
48 | /* index_reg_310.extra_index_reg need to 0 or 7 to work */ | ||
49 | flexcop_ibi_value v30c; | ||
50 | v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid; | ||
51 | v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask; | ||
52 | fc->write_ibi_reg(fc, pid_filter_30c, v30c); | ||
53 | } | ||
54 | |||
55 | static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff) | ||
56 | { | ||
57 | flexcop_set_ibi_value(ctrl_208, Mask_filter_sig, onoff); | ||
58 | } | ||
59 | |||
60 | /* this fancy define reduces the code size of the quite similar PID controlling of | ||
61 | * the first 6 PIDs | ||
62 | */ | ||
63 | |||
64 | #define pid_ctrl(vregname,field,enablefield,trans_field,transval) \ | ||
65 | flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \ | ||
66 | v208 = fc->read_ibi_reg(fc, ctrl_208); \ | ||
67 | vpid.vregname.field = onoff ? pid : 0x1fff; \ | ||
68 | vpid.vregname.trans_field = transval; \ | ||
69 | v208.ctrl_208.enablefield = onoff; \ | ||
70 | fc->write_ibi_reg(fc, vregname, vpid); \ | ||
71 | fc->write_ibi_reg(fc, ctrl_208, v208); | ||
72 | |||
73 | static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, | ||
74 | u16 pid, int onoff) | ||
75 | { | ||
76 | pid_ctrl(pid_filter_300, Stream1_PID, Stream1_filter_sig, | ||
77 | Stream1_trans, 0); | ||
78 | } | ||
79 | |||
80 | static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, | ||
81 | u16 pid, int onoff) | ||
82 | { | ||
83 | pid_ctrl(pid_filter_300, Stream2_PID, Stream2_filter_sig, | ||
84 | Stream2_trans, 0); | ||
85 | } | ||
86 | |||
87 | static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, | ||
88 | u16 pid, int onoff) | ||
89 | { | ||
90 | pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0); | ||
91 | } | ||
92 | |||
93 | static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, | ||
94 | u16 pid, int onoff) | ||
95 | { | ||
96 | pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0); | ||
97 | } | ||
98 | |||
99 | static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, | ||
100 | u16 pid, int onoff) | ||
101 | { | ||
102 | pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0); | ||
103 | } | ||
104 | |||
105 | static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, | ||
106 | u16 pid, int onoff) | ||
107 | { | ||
108 | pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0); | ||
109 | } | ||
110 | |||
111 | static void flexcop_pid_control(struct flexcop_device *fc, | ||
112 | int index, u16 pid, int onoff) | ||
113 | { | ||
114 | if (pid == 0x2000) | ||
115 | return; | ||
116 | |||
117 | deb_ts("setting pid: %5d %04x at index %d '%s'\n", | ||
118 | pid, pid, index, onoff ? "on" : "off"); | ||
119 | |||
120 | /* We could use bit magic here to reduce source code size. | ||
121 | * I decided against it, but to use the real register names */ | ||
122 | switch (index) { | ||
123 | case 0: | ||
124 | flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff); | ||
125 | break; | ||
126 | case 1: | ||
127 | flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff); | ||
128 | break; | ||
129 | case 2: | ||
130 | flexcop_pid_PCR_PID_ctrl(fc, pid, onoff); | ||
131 | break; | ||
132 | case 3: | ||
133 | flexcop_pid_PMT_PID_ctrl(fc, pid, onoff); | ||
134 | break; | ||
135 | case 4: | ||
136 | flexcop_pid_EMM_PID_ctrl(fc, pid, onoff); | ||
137 | break; | ||
138 | case 5: | ||
139 | flexcop_pid_ECM_PID_ctrl(fc, pid, onoff); | ||
140 | break; | ||
141 | default: | ||
142 | if (fc->has_32_hw_pid_filter && index < 38) { | ||
143 | flexcop_ibi_value vpid, vid; | ||
144 | |||
145 | /* set the index */ | ||
146 | vid = fc->read_ibi_reg(fc, index_reg_310); | ||
147 | vid.index_reg_310.index_reg = index - 6; | ||
148 | fc->write_ibi_reg(fc, index_reg_310, vid); | ||
149 | |||
150 | vpid = fc->read_ibi_reg(fc, pid_n_reg_314); | ||
151 | vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; | ||
152 | vpid.pid_n_reg_314.PID_enable_bit = onoff; | ||
153 | fc->write_ibi_reg(fc, pid_n_reg_314, vpid); | ||
154 | } | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff) | ||
160 | { | ||
161 | if (fc->fullts_streaming_state != onoff) { | ||
162 | deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling"); | ||
163 | flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff)); | ||
164 | flexcop_pid_group_filter_ctrl(fc, onoff); | ||
165 | fc->fullts_streaming_state = onoff; | ||
166 | } | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | int flexcop_pid_feed_control(struct flexcop_device *fc, | ||
171 | struct dvb_demux_feed *dvbdmxfeed, int onoff) | ||
172 | { | ||
173 | int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32; | ||
174 | |||
175 | fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */ | ||
176 | if (dvbdmxfeed->index >= max_pid_filter) | ||
177 | fc->extra_feedcount += onoff ? 1 : -1; | ||
178 | |||
179 | /* toggle complete-TS-streaming when: | ||
180 | * - pid_filtering is not enabled and it is the first or last feed requested | ||
181 | * - pid_filtering is enabled, | ||
182 | * - but the number of requested feeds is exceeded | ||
183 | * - or the requested pid is 0x2000 */ | ||
184 | |||
185 | if (!fc->pid_filtering && fc->feedcount == onoff) | ||
186 | flexcop_toggle_fullts_streaming(fc, onoff); | ||
187 | |||
188 | if (fc->pid_filtering) { | ||
189 | flexcop_pid_control \ | ||
190 | (fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff); | ||
191 | |||
192 | if (fc->extra_feedcount > 0) | ||
193 | flexcop_toggle_fullts_streaming(fc, 1); | ||
194 | else if (dvbdmxfeed->pid == 0x2000) | ||
195 | flexcop_toggle_fullts_streaming(fc, onoff); | ||
196 | else | ||
197 | flexcop_toggle_fullts_streaming(fc, 0); | ||
198 | } | ||
199 | |||
200 | /* if it was the first or last feed request change the stream-status */ | ||
201 | if (fc->feedcount == onoff) { | ||
202 | flexcop_rcv_data_ctrl(fc, onoff); | ||
203 | if (fc->stream_control) /* device specific stream control */ | ||
204 | fc->stream_control(fc, onoff); | ||
205 | |||
206 | /* feeding stopped -> reset the flexcop filter*/ | ||
207 | if (onoff == 0) { | ||
208 | flexcop_reset_block_300(fc); | ||
209 | flexcop_hw_filter_init(fc); | ||
210 | } | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | EXPORT_SYMBOL(flexcop_pid_feed_control); | ||
215 | |||
216 | void flexcop_hw_filter_init(struct flexcop_device *fc) | ||
217 | { | ||
218 | int i; | ||
219 | flexcop_ibi_value v; | ||
220 | for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++) | ||
221 | flexcop_pid_control(fc, i, 0x1fff, 0); | ||
222 | |||
223 | flexcop_pid_group_filter(fc, 0, 0x1fe0); | ||
224 | flexcop_pid_group_filter_ctrl(fc, 0); | ||
225 | |||
226 | v = fc->read_ibi_reg(fc, pid_filter_308); | ||
227 | v.pid_filter_308.EMM_filter_4 = 1; | ||
228 | v.pid_filter_308.EMM_filter_6 = 0; | ||
229 | fc->write_ibi_reg(fc, pid_filter_308, v); | ||
230 | |||
231 | flexcop_null_filter_ctrl(fc, 1); | ||
232 | } | ||
diff --git a/drivers/media/common/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c deleted file mode 100644 index 965d5eb3375..00000000000 --- a/drivers/media/common/b2c2/flexcop-i2c.c +++ /dev/null | |||
@@ -1,288 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #include "flexcop.h" | ||
7 | |||
8 | #define FC_MAX_I2C_RETRIES 100000 | ||
9 | |||
10 | static int flexcop_i2c_operation(struct flexcop_device *fc, | ||
11 | flexcop_ibi_value *r100) | ||
12 | { | ||
13 | int i; | ||
14 | flexcop_ibi_value r; | ||
15 | |||
16 | r100->tw_sm_c_100.working_start = 1; | ||
17 | deb_i2c("r100 before: %08x\n",r100->raw); | ||
18 | |||
19 | fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero); | ||
20 | fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */ | ||
21 | |||
22 | for (i = 0; i < FC_MAX_I2C_RETRIES; i++) { | ||
23 | r = fc->read_ibi_reg(fc, tw_sm_c_100); | ||
24 | |||
25 | if (!r.tw_sm_c_100.no_base_addr_ack_error) { | ||
26 | if (r.tw_sm_c_100.st_done) { | ||
27 | *r100 = r; | ||
28 | deb_i2c("i2c success\n"); | ||
29 | return 0; | ||
30 | } | ||
31 | } else { | ||
32 | deb_i2c("suffering from an i2c ack_error\n"); | ||
33 | return -EREMOTEIO; | ||
34 | } | ||
35 | } | ||
36 | deb_i2c("tried %d times i2c operation, " | ||
37 | "never finished or too many ack errors.\n", i); | ||
38 | return -EREMOTEIO; | ||
39 | } | ||
40 | |||
41 | static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, | ||
42 | flexcop_ibi_value r100, u8 *buf) | ||
43 | { | ||
44 | flexcop_ibi_value r104; | ||
45 | int len = r100.tw_sm_c_100.total_bytes, | ||
46 | /* remember total_bytes is buflen-1 */ | ||
47 | ret; | ||
48 | |||
49 | /* work-around to have CableStar2 and SkyStar2 rev 2.7 work | ||
50 | * correctly: | ||
51 | * | ||
52 | * the ITD1000 is behind an i2c-gate which closes automatically | ||
53 | * after an i2c-transaction the STV0297 needs 2 consecutive reads | ||
54 | * one with no_base_addr = 0 and one with 1 | ||
55 | * | ||
56 | * those two work-arounds are conflictin: we check for the card | ||
57 | * type, it is set when probing the ITD1000 */ | ||
58 | if (i2c->fc->dev_type == FC_SKY_REV27) | ||
59 | r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; | ||
60 | |||
61 | ret = flexcop_i2c_operation(i2c->fc, &r100); | ||
62 | if (ret != 0) { | ||
63 | deb_i2c("Retrying operation\n"); | ||
64 | r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; | ||
65 | ret = flexcop_i2c_operation(i2c->fc, &r100); | ||
66 | } | ||
67 | if (ret != 0) { | ||
68 | deb_i2c("read failed. %d\n", ret); | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | buf[0] = r100.tw_sm_c_100.data1_reg; | ||
73 | |||
74 | if (len > 0) { | ||
75 | r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104); | ||
76 | deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw); | ||
77 | |||
78 | /* there is at least one more byte, otherwise we wouldn't be here */ | ||
79 | buf[1] = r104.tw_sm_c_104.data2_reg; | ||
80 | if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; | ||
81 | if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; | ||
82 | } | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int flexcop_i2c_write4(struct flexcop_device *fc, | ||
87 | flexcop_ibi_value r100, u8 *buf) | ||
88 | { | ||
89 | flexcop_ibi_value r104; | ||
90 | int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */ | ||
91 | r104.raw = 0; | ||
92 | |||
93 | /* there is at least one byte, otherwise we wouldn't be here */ | ||
94 | r100.tw_sm_c_100.data1_reg = buf[0]; | ||
95 | r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0; | ||
96 | r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0; | ||
97 | r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0; | ||
98 | |||
99 | deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw); | ||
100 | |||
101 | /* write the additional i2c data before doing the actual i2c operation */ | ||
102 | fc->write_ibi_reg(fc, tw_sm_c_104, r104); | ||
103 | return flexcop_i2c_operation(fc, &r100); | ||
104 | } | ||
105 | |||
106 | int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c, | ||
107 | flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len) | ||
108 | { | ||
109 | int ret; | ||
110 | |||
111 | #ifdef DUMP_I2C_MESSAGES | ||
112 | int i; | ||
113 | #endif | ||
114 | |||
115 | u16 bytes_to_transfer; | ||
116 | flexcop_ibi_value r100; | ||
117 | |||
118 | deb_i2c("op = %d\n",op); | ||
119 | r100.raw = 0; | ||
120 | r100.tw_sm_c_100.chipaddr = chipaddr; | ||
121 | r100.tw_sm_c_100.twoWS_rw = op; | ||
122 | r100.tw_sm_c_100.twoWS_port_reg = i2c->port; | ||
123 | |||
124 | #ifdef DUMP_I2C_MESSAGES | ||
125 | printk(KERN_DEBUG "%d ", i2c->port); | ||
126 | if (op == FC_READ) | ||
127 | printk("rd("); | ||
128 | else | ||
129 | printk("wr("); | ||
130 | printk("%02x): %02x ", chipaddr, addr); | ||
131 | #endif | ||
132 | |||
133 | /* in that case addr is the only value -> | ||
134 | * we write it twice as baseaddr and val0 | ||
135 | * BBTI is doing it like that for ISL6421 at least */ | ||
136 | if (i2c->no_base_addr && len == 0 && op == FC_WRITE) { | ||
137 | buf = &addr; | ||
138 | len = 1; | ||
139 | } | ||
140 | |||
141 | while (len != 0) { | ||
142 | bytes_to_transfer = len > 4 ? 4 : len; | ||
143 | |||
144 | r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1; | ||
145 | r100.tw_sm_c_100.baseaddr = addr; | ||
146 | |||
147 | if (op == FC_READ) | ||
148 | ret = flexcop_i2c_read4(i2c, r100, buf); | ||
149 | else | ||
150 | ret = flexcop_i2c_write4(i2c->fc, r100, buf); | ||
151 | |||
152 | #ifdef DUMP_I2C_MESSAGES | ||
153 | for (i = 0; i < bytes_to_transfer; i++) | ||
154 | printk("%02x ", buf[i]); | ||
155 | #endif | ||
156 | |||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | |||
160 | buf += bytes_to_transfer; | ||
161 | addr += bytes_to_transfer; | ||
162 | len -= bytes_to_transfer; | ||
163 | } | ||
164 | |||
165 | #ifdef DUMP_I2C_MESSAGES | ||
166 | printk("\n"); | ||
167 | #endif | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | /* exported for PCI i2c */ | ||
172 | EXPORT_SYMBOL(flexcop_i2c_request); | ||
173 | |||
174 | /* master xfer callback for demodulator */ | ||
175 | static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, | ||
176 | struct i2c_msg msgs[], int num) | ||
177 | { | ||
178 | struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); | ||
179 | int i, ret = 0; | ||
180 | |||
181 | /* Some drivers use 1 byte or 0 byte reads as probes, which this | ||
182 | * driver doesn't support. These probes will always fail, so this | ||
183 | * hack makes them always succeed. If one knew how, it would of | ||
184 | * course be better to actually do the read. */ | ||
185 | if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1) | ||
186 | return 1; | ||
187 | |||
188 | if (mutex_lock_interruptible(&i2c->fc->i2c_mutex)) | ||
189 | return -ERESTARTSYS; | ||
190 | |||
191 | for (i = 0; i < num; i++) { | ||
192 | /* reading */ | ||
193 | if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) { | ||
194 | ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr, | ||
195 | msgs[i].buf[0], msgs[i+1].buf, | ||
196 | msgs[i+1].len); | ||
197 | i++; /* skip the following message */ | ||
198 | } else /* writing */ | ||
199 | ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr, | ||
200 | msgs[i].buf[0], &msgs[i].buf[1], | ||
201 | msgs[i].len - 1); | ||
202 | if (ret < 0) { | ||
203 | deb_i2c("i2c master_xfer failed"); | ||
204 | break; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | mutex_unlock(&i2c->fc->i2c_mutex); | ||
209 | |||
210 | if (ret == 0) | ||
211 | ret = num; | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static u32 flexcop_i2c_func(struct i2c_adapter *adapter) | ||
216 | { | ||
217 | return I2C_FUNC_I2C; | ||
218 | } | ||
219 | |||
220 | static struct i2c_algorithm flexcop_algo = { | ||
221 | .master_xfer = flexcop_master_xfer, | ||
222 | .functionality = flexcop_i2c_func, | ||
223 | }; | ||
224 | |||
225 | int flexcop_i2c_init(struct flexcop_device *fc) | ||
226 | { | ||
227 | int ret; | ||
228 | mutex_init(&fc->i2c_mutex); | ||
229 | |||
230 | fc->fc_i2c_adap[0].fc = fc; | ||
231 | fc->fc_i2c_adap[1].fc = fc; | ||
232 | fc->fc_i2c_adap[2].fc = fc; | ||
233 | fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD; | ||
234 | fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; | ||
235 | fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; | ||
236 | |||
237 | strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod", | ||
238 | sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); | ||
239 | strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom", | ||
240 | sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); | ||
241 | strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner", | ||
242 | sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); | ||
243 | |||
244 | i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]); | ||
245 | i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]); | ||
246 | i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]); | ||
247 | |||
248 | fc->fc_i2c_adap[0].i2c_adap.algo = | ||
249 | fc->fc_i2c_adap[1].i2c_adap.algo = | ||
250 | fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo; | ||
251 | fc->fc_i2c_adap[0].i2c_adap.algo_data = | ||
252 | fc->fc_i2c_adap[1].i2c_adap.algo_data = | ||
253 | fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL; | ||
254 | fc->fc_i2c_adap[0].i2c_adap.dev.parent = | ||
255 | fc->fc_i2c_adap[1].i2c_adap.dev.parent = | ||
256 | fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev; | ||
257 | |||
258 | ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap); | ||
259 | if (ret < 0) | ||
260 | return ret; | ||
261 | |||
262 | ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap); | ||
263 | if (ret < 0) | ||
264 | goto adap_1_failed; | ||
265 | |||
266 | ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap); | ||
267 | if (ret < 0) | ||
268 | goto adap_2_failed; | ||
269 | |||
270 | fc->init_state |= FC_STATE_I2C_INIT; | ||
271 | return 0; | ||
272 | |||
273 | adap_2_failed: | ||
274 | i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); | ||
275 | adap_1_failed: | ||
276 | i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | void flexcop_i2c_exit(struct flexcop_device *fc) | ||
281 | { | ||
282 | if (fc->init_state & FC_STATE_I2C_INIT) { | ||
283 | i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap); | ||
284 | i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); | ||
285 | i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); | ||
286 | } | ||
287 | fc->init_state &= ~FC_STATE_I2C_INIT; | ||
288 | } | ||
diff --git a/drivers/media/common/b2c2/flexcop-misc.c b/drivers/media/common/b2c2/flexcop-misc.c deleted file mode 100644 index f06f3a9070f..00000000000 --- a/drivers/media/common/b2c2/flexcop-misc.c +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-misc.c - miscellaneous functions | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #include "flexcop.h" | ||
7 | |||
8 | void flexcop_determine_revision(struct flexcop_device *fc) | ||
9 | { | ||
10 | flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); | ||
11 | |||
12 | switch (v.misc_204.Rev_N_sig_revision_hi) { | ||
13 | case 0x2: | ||
14 | deb_info("found a FlexCopII.\n"); | ||
15 | fc->rev = FLEXCOP_II; | ||
16 | break; | ||
17 | case 0x3: | ||
18 | deb_info("found a FlexCopIIb.\n"); | ||
19 | fc->rev = FLEXCOP_IIB; | ||
20 | break; | ||
21 | case 0x0: | ||
22 | deb_info("found a FlexCopIII.\n"); | ||
23 | fc->rev = FLEXCOP_III; | ||
24 | break; | ||
25 | default: | ||
26 | err("unknown FlexCop Revision: %x. Please report this to " | ||
27 | "linux-dvb@linuxtv.org.", | ||
28 | v.misc_204.Rev_N_sig_revision_hi); | ||
29 | break; | ||
30 | } | ||
31 | |||
32 | if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps)) | ||
33 | deb_info("this FlexCop has " | ||
34 | "the additional 32 hardware pid filter.\n"); | ||
35 | else | ||
36 | deb_info("this FlexCop has " | ||
37 | "the 6 basic main hardware pid filter.\n"); | ||
38 | /* bus parts have to decide if hw pid filtering is used or not. */ | ||
39 | } | ||
40 | |||
41 | static const char *flexcop_revision_names[] = { | ||
42 | "Unknown chip", | ||
43 | "FlexCopII", | ||
44 | "FlexCopIIb", | ||
45 | "FlexCopIII", | ||
46 | }; | ||
47 | |||
48 | static const char *flexcop_device_names[] = { | ||
49 | [FC_UNK] = "Unknown device", | ||
50 | [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C", | ||
51 | [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T", | ||
52 | [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation", | ||
53 | [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation", | ||
54 | [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", | ||
55 | [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)", | ||
56 | [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", | ||
57 | [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", | ||
58 | [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", | ||
59 | }; | ||
60 | |||
61 | static const char *flexcop_bus_names[] = { | ||
62 | "USB", | ||
63 | "PCI", | ||
64 | }; | ||
65 | |||
66 | void flexcop_device_name(struct flexcop_device *fc, | ||
67 | const char *prefix, const char *suffix) | ||
68 | { | ||
69 | info("%s '%s' at the '%s' bus controlled by a '%s' %s", | ||
70 | prefix, flexcop_device_names[fc->dev_type], | ||
71 | flexcop_bus_names[fc->bus_type], | ||
72 | flexcop_revision_names[fc->rev], suffix); | ||
73 | } | ||
74 | |||
75 | void flexcop_dump_reg(struct flexcop_device *fc, | ||
76 | flexcop_ibi_register reg, int num) | ||
77 | { | ||
78 | flexcop_ibi_value v; | ||
79 | int i; | ||
80 | for (i = 0; i < num; i++) { | ||
81 | v = fc->read_ibi_reg(fc, reg+4*i); | ||
82 | deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw); | ||
83 | } | ||
84 | deb_rdump("\n"); | ||
85 | } | ||
86 | EXPORT_SYMBOL(flexcop_dump_reg); | ||
diff --git a/drivers/media/common/b2c2/flexcop-reg.h b/drivers/media/common/b2c2/flexcop-reg.h deleted file mode 100644 index dc4528dcbb9..00000000000 --- a/drivers/media/common/b2c2/flexcop-reg.h +++ /dev/null | |||
@@ -1,166 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #ifndef __FLEXCOP_REG_H__ | ||
7 | #define __FLEXCOP_REG_H__ | ||
8 | |||
9 | typedef enum { | ||
10 | FLEXCOP_UNK = 0, | ||
11 | FLEXCOP_II, | ||
12 | FLEXCOP_IIB, | ||
13 | FLEXCOP_III, | ||
14 | } flexcop_revision_t; | ||
15 | |||
16 | typedef enum { | ||
17 | FC_UNK = 0, | ||
18 | FC_CABLE, | ||
19 | FC_AIR_DVBT, | ||
20 | FC_AIR_ATSC1, | ||
21 | FC_AIR_ATSC2, | ||
22 | FC_AIR_ATSC3, | ||
23 | FC_SKY_REV23, | ||
24 | FC_SKY_REV26, | ||
25 | FC_SKY_REV27, | ||
26 | FC_SKY_REV28, | ||
27 | } flexcop_device_type_t; | ||
28 | |||
29 | typedef enum { | ||
30 | FC_USB = 0, | ||
31 | FC_PCI, | ||
32 | } flexcop_bus_t; | ||
33 | |||
34 | /* FlexCop IBI Registers */ | ||
35 | #if defined(__LITTLE_ENDIAN) | ||
36 | #include "flexcop_ibi_value_le.h" | ||
37 | #else | ||
38 | #if defined(__BIG_ENDIAN) | ||
39 | #include "flexcop_ibi_value_be.h" | ||
40 | #else | ||
41 | #error no endian defined | ||
42 | #endif | ||
43 | #endif | ||
44 | |||
45 | #define fc_data_Tag_ID_DVB 0x3e | ||
46 | #define fc_data_Tag_ID_ATSC 0x3f | ||
47 | #define fc_data_Tag_ID_IDSB 0x8b | ||
48 | |||
49 | #define fc_key_code_default 0x1 | ||
50 | #define fc_key_code_even 0x2 | ||
51 | #define fc_key_code_odd 0x3 | ||
52 | |||
53 | extern flexcop_ibi_value ibi_zero; | ||
54 | |||
55 | typedef enum { | ||
56 | FC_I2C_PORT_DEMOD = 1, | ||
57 | FC_I2C_PORT_EEPROM = 2, | ||
58 | FC_I2C_PORT_TUNER = 3, | ||
59 | } flexcop_i2c_port_t; | ||
60 | |||
61 | typedef enum { | ||
62 | FC_WRITE = 0, | ||
63 | FC_READ = 1, | ||
64 | } flexcop_access_op_t; | ||
65 | |||
66 | typedef enum { | ||
67 | FC_SRAM_DEST_NET = 1, | ||
68 | FC_SRAM_DEST_CAI = 2, | ||
69 | FC_SRAM_DEST_CAO = 4, | ||
70 | FC_SRAM_DEST_MEDIA = 8 | ||
71 | } flexcop_sram_dest_t; | ||
72 | |||
73 | typedef enum { | ||
74 | FC_SRAM_DEST_TARGET_WAN_USB = 0, | ||
75 | FC_SRAM_DEST_TARGET_DMA1 = 1, | ||
76 | FC_SRAM_DEST_TARGET_DMA2 = 2, | ||
77 | FC_SRAM_DEST_TARGET_FC3_CA = 3 | ||
78 | } flexcop_sram_dest_target_t; | ||
79 | |||
80 | typedef enum { | ||
81 | FC_SRAM_2_32KB = 0, /* 64KB */ | ||
82 | FC_SRAM_1_32KB = 1, /* 32KB - default fow FCII */ | ||
83 | FC_SRAM_1_128KB = 2, /* 128KB */ | ||
84 | FC_SRAM_1_48KB = 3, /* 48KB - default for FCIII */ | ||
85 | } flexcop_sram_type_t; | ||
86 | |||
87 | typedef enum { | ||
88 | FC_WAN_SPEED_4MBITS = 0, | ||
89 | FC_WAN_SPEED_8MBITS = 1, | ||
90 | FC_WAN_SPEED_12MBITS = 2, | ||
91 | FC_WAN_SPEED_16MBITS = 3, | ||
92 | } flexcop_wan_speed_t; | ||
93 | |||
94 | typedef enum { | ||
95 | FC_DMA_1 = 1, | ||
96 | FC_DMA_2 = 2, | ||
97 | } flexcop_dma_index_t; | ||
98 | |||
99 | typedef enum { | ||
100 | FC_DMA_SUBADDR_0 = 1, | ||
101 | FC_DMA_SUBADDR_1 = 2, | ||
102 | } flexcop_dma_addr_index_t; | ||
103 | |||
104 | /* names of the particular registers */ | ||
105 | typedef enum { | ||
106 | dma1_000 = 0x000, | ||
107 | dma1_004 = 0x004, | ||
108 | dma1_008 = 0x008, | ||
109 | dma1_00c = 0x00c, | ||
110 | dma2_010 = 0x010, | ||
111 | dma2_014 = 0x014, | ||
112 | dma2_018 = 0x018, | ||
113 | dma2_01c = 0x01c, | ||
114 | |||
115 | tw_sm_c_100 = 0x100, | ||
116 | tw_sm_c_104 = 0x104, | ||
117 | tw_sm_c_108 = 0x108, | ||
118 | tw_sm_c_10c = 0x10c, | ||
119 | tw_sm_c_110 = 0x110, | ||
120 | |||
121 | lnb_switch_freq_200 = 0x200, | ||
122 | misc_204 = 0x204, | ||
123 | ctrl_208 = 0x208, | ||
124 | irq_20c = 0x20c, | ||
125 | sw_reset_210 = 0x210, | ||
126 | misc_214 = 0x214, | ||
127 | mbox_v8_to_host_218 = 0x218, | ||
128 | mbox_host_to_v8_21c = 0x21c, | ||
129 | |||
130 | pid_filter_300 = 0x300, | ||
131 | pid_filter_304 = 0x304, | ||
132 | pid_filter_308 = 0x308, | ||
133 | pid_filter_30c = 0x30c, | ||
134 | index_reg_310 = 0x310, | ||
135 | pid_n_reg_314 = 0x314, | ||
136 | mac_low_reg_318 = 0x318, | ||
137 | mac_high_reg_31c = 0x31c, | ||
138 | |||
139 | data_tag_400 = 0x400, | ||
140 | card_id_408 = 0x408, | ||
141 | card_id_40c = 0x40c, | ||
142 | mac_address_418 = 0x418, | ||
143 | mac_address_41c = 0x41c, | ||
144 | |||
145 | ci_600 = 0x600, | ||
146 | pi_604 = 0x604, | ||
147 | pi_608 = 0x608, | ||
148 | dvb_reg_60c = 0x60c, | ||
149 | |||
150 | sram_ctrl_reg_700 = 0x700, | ||
151 | net_buf_reg_704 = 0x704, | ||
152 | cai_buf_reg_708 = 0x708, | ||
153 | cao_buf_reg_70c = 0x70c, | ||
154 | media_buf_reg_710 = 0x710, | ||
155 | sram_dest_reg_714 = 0x714, | ||
156 | net_buf_reg_718 = 0x718, | ||
157 | wan_ctrl_reg_71c = 0x71c, | ||
158 | } flexcop_ibi_register; | ||
159 | |||
160 | #define flexcop_set_ibi_value(reg,attr,val) { \ | ||
161 | flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \ | ||
162 | v.reg.attr = val; \ | ||
163 | fc->write_ibi_reg(fc,reg,v); \ | ||
164 | } | ||
165 | |||
166 | #endif | ||
diff --git a/drivers/media/common/b2c2/flexcop-sram.c b/drivers/media/common/b2c2/flexcop-sram.c deleted file mode 100644 index f2199e43e80..00000000000 --- a/drivers/media/common/b2c2/flexcop-sram.c +++ /dev/null | |||
@@ -1,363 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop-sram.c - functions for controlling the SRAM | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #include "flexcop.h" | ||
7 | |||
8 | static void flexcop_sram_set_chip(struct flexcop_device *fc, | ||
9 | flexcop_sram_type_t type) | ||
10 | { | ||
11 | flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type); | ||
12 | } | ||
13 | |||
14 | int flexcop_sram_init(struct flexcop_device *fc) | ||
15 | { | ||
16 | switch (fc->rev) { | ||
17 | case FLEXCOP_II: | ||
18 | case FLEXCOP_IIB: | ||
19 | flexcop_sram_set_chip(fc, FC_SRAM_1_32KB); | ||
20 | break; | ||
21 | case FLEXCOP_III: | ||
22 | flexcop_sram_set_chip(fc, FC_SRAM_1_48KB); | ||
23 | break; | ||
24 | default: | ||
25 | return -EINVAL; | ||
26 | } | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, | ||
31 | flexcop_sram_dest_target_t target) | ||
32 | { | ||
33 | flexcop_ibi_value v; | ||
34 | v = fc->read_ibi_reg(fc, sram_dest_reg_714); | ||
35 | |||
36 | if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) { | ||
37 | err("SRAM destination target to available on FlexCopII(b)\n"); | ||
38 | return -EINVAL; | ||
39 | } | ||
40 | deb_sram("sram dest: %x target: %x\n", dest, target); | ||
41 | |||
42 | if (dest & FC_SRAM_DEST_NET) | ||
43 | v.sram_dest_reg_714.NET_Dest = target; | ||
44 | if (dest & FC_SRAM_DEST_CAI) | ||
45 | v.sram_dest_reg_714.CAI_Dest = target; | ||
46 | if (dest & FC_SRAM_DEST_CAO) | ||
47 | v.sram_dest_reg_714.CAO_Dest = target; | ||
48 | if (dest & FC_SRAM_DEST_MEDIA) | ||
49 | v.sram_dest_reg_714.MEDIA_Dest = target; | ||
50 | |||
51 | fc->write_ibi_reg(fc,sram_dest_reg_714,v); | ||
52 | udelay(1000); /* TODO delay really necessary */ | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | EXPORT_SYMBOL(flexcop_sram_set_dest); | ||
57 | |||
58 | void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s) | ||
59 | { | ||
60 | flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s); | ||
61 | } | ||
62 | EXPORT_SYMBOL(flexcop_wan_set_speed); | ||
63 | |||
64 | void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill) | ||
65 | { | ||
66 | flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); | ||
67 | v.sram_dest_reg_714.ctrl_usb_wan = usb_wan; | ||
68 | v.sram_dest_reg_714.ctrl_sramdma = sramdma; | ||
69 | v.sram_dest_reg_714.ctrl_maximumfill = maximumfill; | ||
70 | fc->write_ibi_reg(fc,sram_dest_reg_714,v); | ||
71 | } | ||
72 | EXPORT_SYMBOL(flexcop_sram_ctrl); | ||
73 | |||
74 | #if 0 | ||
75 | static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len) | ||
76 | { | ||
77 | int i, retries; | ||
78 | u32 command; | ||
79 | |||
80 | for (i = 0; i < len; i++) { | ||
81 | command = bank | addr | 0x04000000 | (*buf << 0x10); | ||
82 | |||
83 | retries = 2; | ||
84 | |||
85 | while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { | ||
86 | mdelay(1); | ||
87 | retries--; | ||
88 | }; | ||
89 | |||
90 | if (retries == 0) | ||
91 | printk("%s: SRAM timeout\n", __func__); | ||
92 | |||
93 | write_reg_dw(adapter, 0x700, command); | ||
94 | |||
95 | buf++; | ||
96 | addr++; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len) | ||
101 | { | ||
102 | int i, retries; | ||
103 | u32 command, value; | ||
104 | |||
105 | for (i = 0; i < len; i++) { | ||
106 | command = bank | addr | 0x04008000; | ||
107 | |||
108 | retries = 10000; | ||
109 | |||
110 | while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { | ||
111 | mdelay(1); | ||
112 | retries--; | ||
113 | }; | ||
114 | |||
115 | if (retries == 0) | ||
116 | printk("%s: SRAM timeout\n", __func__); | ||
117 | |||
118 | write_reg_dw(adapter, 0x700, command); | ||
119 | |||
120 | retries = 10000; | ||
121 | |||
122 | while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { | ||
123 | mdelay(1); | ||
124 | retries--; | ||
125 | }; | ||
126 | |||
127 | if (retries == 0) | ||
128 | printk("%s: SRAM timeout\n", __func__); | ||
129 | |||
130 | value = read_reg_dw(adapter, 0x700) >> 0x10; | ||
131 | |||
132 | *buf = (value & 0xff); | ||
133 | |||
134 | addr++; | ||
135 | buf++; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) | ||
140 | { | ||
141 | u32 bank; | ||
142 | |||
143 | bank = 0; | ||
144 | |||
145 | if (adapter->dw_sram_type == 0x20000) { | ||
146 | bank = (addr & 0x18000) << 0x0d; | ||
147 | } | ||
148 | |||
149 | if (adapter->dw_sram_type == 0x00000) { | ||
150 | if ((addr >> 0x0f) == 0) | ||
151 | bank = 0x20000000; | ||
152 | else | ||
153 | bank = 0x10000000; | ||
154 | } | ||
155 | flex_sram_write(adapter, bank, addr & 0x7fff, buf, len); | ||
156 | } | ||
157 | |||
158 | static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) | ||
159 | { | ||
160 | u32 bank; | ||
161 | bank = 0; | ||
162 | |||
163 | if (adapter->dw_sram_type == 0x20000) { | ||
164 | bank = (addr & 0x18000) << 0x0d; | ||
165 | } | ||
166 | |||
167 | if (adapter->dw_sram_type == 0x00000) { | ||
168 | if ((addr >> 0x0f) == 0) | ||
169 | bank = 0x20000000; | ||
170 | else | ||
171 | bank = 0x10000000; | ||
172 | } | ||
173 | flex_sram_read(adapter, bank, addr & 0x7fff, buf, len); | ||
174 | } | ||
175 | |||
176 | static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len) | ||
177 | { | ||
178 | u32 length; | ||
179 | while (len != 0) { | ||
180 | length = len; | ||
181 | /* check if the address range belongs to the same | ||
182 | * 32K memory chip. If not, the data is read | ||
183 | * from one chip at a time */ | ||
184 | if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { | ||
185 | length = (((addr >> 0x0f) + 1) << 0x0f) - addr; | ||
186 | } | ||
187 | |||
188 | sram_read_chunk(adapter, addr, buf, length); | ||
189 | addr = addr + length; | ||
190 | buf = buf + length; | ||
191 | len = len - length; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len) | ||
196 | { | ||
197 | u32 length; | ||
198 | while (len != 0) { | ||
199 | length = len; | ||
200 | |||
201 | /* check if the address range belongs to the same | ||
202 | * 32K memory chip. If not, the data is | ||
203 | * written to one chip at a time */ | ||
204 | if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { | ||
205 | length = (((addr >> 0x0f) + 1) << 0x0f) - addr; | ||
206 | } | ||
207 | |||
208 | sram_write_chunk(adapter, addr, buf, length); | ||
209 | addr = addr + length; | ||
210 | buf = buf + length; | ||
211 | len = len - length; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static void sram_set_size(struct adapter *adapter, u32 mask) | ||
216 | { | ||
217 | write_reg_dw(adapter, 0x71c, | ||
218 | (mask | (~0x30000 & read_reg_dw(adapter, 0x71c)))); | ||
219 | } | ||
220 | |||
221 | static void sram_init(struct adapter *adapter) | ||
222 | { | ||
223 | u32 tmp; | ||
224 | tmp = read_reg_dw(adapter, 0x71c); | ||
225 | write_reg_dw(adapter, 0x71c, 1); | ||
226 | |||
227 | if (read_reg_dw(adapter, 0x71c) != 0) { | ||
228 | write_reg_dw(adapter, 0x71c, tmp); | ||
229 | adapter->dw_sram_type = tmp & 0x30000; | ||
230 | ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); | ||
231 | } else { | ||
232 | adapter->dw_sram_type = 0x10000; | ||
233 | ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) | ||
238 | { | ||
239 | u8 tmp1, tmp2; | ||
240 | dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr); | ||
241 | |||
242 | sram_set_size(adapter, mask); | ||
243 | sram_init(adapter); | ||
244 | |||
245 | tmp2 = 0xa5; | ||
246 | tmp1 = 0x4f; | ||
247 | |||
248 | sram_write(adapter, addr, &tmp2, 1); | ||
249 | sram_write(adapter, addr + 4, &tmp1, 1); | ||
250 | |||
251 | tmp2 = 0; | ||
252 | mdelay(20); | ||
253 | |||
254 | sram_read(adapter, addr, &tmp2, 1); | ||
255 | sram_read(adapter, addr, &tmp2, 1); | ||
256 | |||
257 | dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2); | ||
258 | |||
259 | if (tmp2 != 0xa5) | ||
260 | return 0; | ||
261 | |||
262 | tmp2 = 0x5a; | ||
263 | tmp1 = 0xf4; | ||
264 | |||
265 | sram_write(adapter, addr, &tmp2, 1); | ||
266 | sram_write(adapter, addr + 4, &tmp1, 1); | ||
267 | |||
268 | tmp2 = 0; | ||
269 | mdelay(20); | ||
270 | |||
271 | sram_read(adapter, addr, &tmp2, 1); | ||
272 | sram_read(adapter, addr, &tmp2, 1); | ||
273 | |||
274 | dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2); | ||
275 | |||
276 | if (tmp2 != 0x5a) | ||
277 | return 0; | ||
278 | return 1; | ||
279 | } | ||
280 | |||
281 | static u32 sram_length(struct adapter *adapter) | ||
282 | { | ||
283 | if (adapter->dw_sram_type == 0x10000) | ||
284 | return 32768; /* 32K */ | ||
285 | if (adapter->dw_sram_type == 0x00000) | ||
286 | return 65536; /* 64K */ | ||
287 | if (adapter->dw_sram_type == 0x20000) | ||
288 | return 131072; /* 128K */ | ||
289 | return 32768; /* 32K */ | ||
290 | } | ||
291 | |||
292 | /* FlexcopII can work with 32K, 64K or 128K of external SRAM memory. | ||
293 | - for 128K there are 4x32K chips at bank 0,1,2,3. | ||
294 | - for 64K there are 2x32K chips at bank 1,2. | ||
295 | - for 32K there is one 32K chip at bank 0. | ||
296 | |||
297 | FlexCop works only with one bank at a time. The bank is selected | ||
298 | by bits 28-29 of the 0x700 register. | ||
299 | |||
300 | bank 0 covers addresses 0x00000-0x07fff | ||
301 | bank 1 covers addresses 0x08000-0x0ffff | ||
302 | bank 2 covers addresses 0x10000-0x17fff | ||
303 | bank 3 covers addresses 0x18000-0x1ffff */ | ||
304 | |||
305 | static int flexcop_sram_detect(struct flexcop_device *fc) | ||
306 | { | ||
307 | flexcop_ibi_value r208, r71c_0, vr71c_1; | ||
308 | r208 = fc->read_ibi_reg(fc, ctrl_208); | ||
309 | fc->write_ibi_reg(fc, ctrl_208, ibi_zero); | ||
310 | |||
311 | r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c); | ||
312 | write_reg_dw(adapter, 0x71c, 1); | ||
313 | tmp3 = read_reg_dw(adapter, 0x71c); | ||
314 | dprintk("%s: tmp3 = %x\n", __func__, tmp3); | ||
315 | write_reg_dw(adapter, 0x71c, tmp2); | ||
316 | |||
317 | // check for internal SRAM ??? | ||
318 | tmp3--; | ||
319 | if (tmp3 != 0) { | ||
320 | sram_set_size(adapter, 0x10000); | ||
321 | sram_init(adapter); | ||
322 | write_reg_dw(adapter, 0x208, tmp); | ||
323 | dprintk("%s: sram size = 32K\n", __func__); | ||
324 | return 32; | ||
325 | } | ||
326 | |||
327 | if (sram_test_location(adapter, 0x20000, 0x18000) != 0) { | ||
328 | sram_set_size(adapter, 0x20000); | ||
329 | sram_init(adapter); | ||
330 | write_reg_dw(adapter, 0x208, tmp); | ||
331 | dprintk("%s: sram size = 128K\n", __func__); | ||
332 | return 128; | ||
333 | } | ||
334 | |||
335 | if (sram_test_location(adapter, 0x00000, 0x10000) != 0) { | ||
336 | sram_set_size(adapter, 0x00000); | ||
337 | sram_init(adapter); | ||
338 | write_reg_dw(adapter, 0x208, tmp); | ||
339 | dprintk("%s: sram size = 64K\n", __func__); | ||
340 | return 64; | ||
341 | } | ||
342 | |||
343 | if (sram_test_location(adapter, 0x10000, 0x00000) != 0) { | ||
344 | sram_set_size(adapter, 0x10000); | ||
345 | sram_init(adapter); | ||
346 | write_reg_dw(adapter, 0x208, tmp); | ||
347 | dprintk("%s: sram size = 32K\n", __func__); | ||
348 | return 32; | ||
349 | } | ||
350 | |||
351 | sram_set_size(adapter, 0x10000); | ||
352 | sram_init(adapter); | ||
353 | write_reg_dw(adapter, 0x208, tmp); | ||
354 | dprintk("%s: SRAM detection failed. Set to 32K \n", __func__); | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static void sll_detect_sram_size(struct adapter *adapter) | ||
359 | { | ||
360 | sram_detect_for_flex2(adapter); | ||
361 | } | ||
362 | |||
363 | #endif | ||
diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c deleted file mode 100644 index 412c5daf2b4..00000000000 --- a/drivers/media/common/b2c2/flexcop.c +++ /dev/null | |||
@@ -1,325 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop.c - main module part | ||
4 | * Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de> | ||
5 | * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc | ||
6 | * | ||
7 | * Acknowledgements: | ||
8 | * John Jurrius from BBTI, Inc. for extensive support | ||
9 | * with code examples and data books | ||
10 | * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting) | ||
11 | * | ||
12 | * Contributions to the skystar2-driver have been done by | ||
13 | * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes) | ||
14 | * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code) | ||
15 | * Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu) | ||
16 | * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac | ||
17 | * filtering) | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or | ||
20 | * modify it under the terms of the GNU Lesser General Public License | ||
21 | * as published by the Free Software Foundation; either version 2.1 | ||
22 | * of the License, or (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU Lesser General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
32 | */ | ||
33 | |||
34 | #include "flexcop.h" | ||
35 | |||
36 | #define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip" | ||
37 | #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de" | ||
38 | |||
39 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | ||
40 | #define DEBSTATUS "" | ||
41 | #else | ||
42 | #define DEBSTATUS " (debugging is not enabled)" | ||
43 | #endif | ||
44 | |||
45 | int b2c2_flexcop_debug; | ||
46 | EXPORT_SYMBOL_GPL(b2c2_flexcop_debug); | ||
47 | module_param_named(debug, b2c2_flexcop_debug, int, 0644); | ||
48 | MODULE_PARM_DESC(debug, | ||
49 | "set debug level (1=info,2=tuner,4=i2c,8=ts," | ||
50 | "16=sram,32=reg (|-able))." | ||
51 | DEBSTATUS); | ||
52 | #undef DEBSTATUS | ||
53 | |||
54 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
55 | |||
56 | /* global zero for ibi values */ | ||
57 | flexcop_ibi_value ibi_zero; | ||
58 | |||
59 | static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
60 | { | ||
61 | struct flexcop_device *fc = dvbdmxfeed->demux->priv; | ||
62 | return flexcop_pid_feed_control(fc, dvbdmxfeed, 1); | ||
63 | } | ||
64 | |||
65 | static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
66 | { | ||
67 | struct flexcop_device *fc = dvbdmxfeed->demux->priv; | ||
68 | return flexcop_pid_feed_control(fc, dvbdmxfeed, 0); | ||
69 | } | ||
70 | |||
71 | static int flexcop_dvb_init(struct flexcop_device *fc) | ||
72 | { | ||
73 | int ret = dvb_register_adapter(&fc->dvb_adapter, | ||
74 | "FlexCop Digital TV device", fc->owner, | ||
75 | fc->dev, adapter_nr); | ||
76 | if (ret < 0) { | ||
77 | err("error registering DVB adapter"); | ||
78 | return ret; | ||
79 | } | ||
80 | fc->dvb_adapter.priv = fc; | ||
81 | |||
82 | fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | ||
83 | | DMX_MEMORY_BASED_FILTERING); | ||
84 | fc->demux.priv = fc; | ||
85 | fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED; | ||
86 | fc->demux.start_feed = flexcop_dvb_start_feed; | ||
87 | fc->demux.stop_feed = flexcop_dvb_stop_feed; | ||
88 | fc->demux.write_to_decoder = NULL; | ||
89 | |||
90 | ret = dvb_dmx_init(&fc->demux); | ||
91 | if (ret < 0) { | ||
92 | err("dvb_dmx failed: error %d", ret); | ||
93 | goto err_dmx; | ||
94 | } | ||
95 | |||
96 | fc->hw_frontend.source = DMX_FRONTEND_0; | ||
97 | |||
98 | fc->dmxdev.filternum = fc->demux.feednum; | ||
99 | fc->dmxdev.demux = &fc->demux.dmx; | ||
100 | fc->dmxdev.capabilities = 0; | ||
101 | ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter); | ||
102 | if (ret < 0) { | ||
103 | err("dvb_dmxdev_init failed: error %d", ret); | ||
104 | goto err_dmx_dev; | ||
105 | } | ||
106 | |||
107 | ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend); | ||
108 | if (ret < 0) { | ||
109 | err("adding hw_frontend to dmx failed: error %d", ret); | ||
110 | goto err_dmx_add_hw_frontend; | ||
111 | } | ||
112 | |||
113 | fc->mem_frontend.source = DMX_MEMORY_FE; | ||
114 | ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend); | ||
115 | if (ret < 0) { | ||
116 | err("adding mem_frontend to dmx failed: error %d", ret); | ||
117 | goto err_dmx_add_mem_frontend; | ||
118 | } | ||
119 | |||
120 | ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend); | ||
121 | if (ret < 0) { | ||
122 | err("connect frontend failed: error %d", ret); | ||
123 | goto err_connect_frontend; | ||
124 | } | ||
125 | |||
126 | ret = dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx); | ||
127 | if (ret < 0) { | ||
128 | err("dvb_net_init failed: error %d", ret); | ||
129 | goto err_net; | ||
130 | } | ||
131 | |||
132 | fc->init_state |= FC_STATE_DVB_INIT; | ||
133 | return 0; | ||
134 | |||
135 | err_net: | ||
136 | fc->demux.dmx.disconnect_frontend(&fc->demux.dmx); | ||
137 | err_connect_frontend: | ||
138 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend); | ||
139 | err_dmx_add_mem_frontend: | ||
140 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->hw_frontend); | ||
141 | err_dmx_add_hw_frontend: | ||
142 | dvb_dmxdev_release(&fc->dmxdev); | ||
143 | err_dmx_dev: | ||
144 | dvb_dmx_release(&fc->demux); | ||
145 | err_dmx: | ||
146 | dvb_unregister_adapter(&fc->dvb_adapter); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static void flexcop_dvb_exit(struct flexcop_device *fc) | ||
151 | { | ||
152 | if (fc->init_state & FC_STATE_DVB_INIT) { | ||
153 | dvb_net_release(&fc->dvbnet); | ||
154 | |||
155 | fc->demux.dmx.close(&fc->demux.dmx); | ||
156 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, | ||
157 | &fc->mem_frontend); | ||
158 | fc->demux.dmx.remove_frontend(&fc->demux.dmx, | ||
159 | &fc->hw_frontend); | ||
160 | dvb_dmxdev_release(&fc->dmxdev); | ||
161 | dvb_dmx_release(&fc->demux); | ||
162 | dvb_unregister_adapter(&fc->dvb_adapter); | ||
163 | deb_info("deinitialized dvb stuff\n"); | ||
164 | } | ||
165 | fc->init_state &= ~FC_STATE_DVB_INIT; | ||
166 | } | ||
167 | |||
168 | /* these methods are necessary to achieve the long-term-goal of hiding the | ||
169 | * struct flexcop_device from the bus-parts */ | ||
170 | void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len) | ||
171 | { | ||
172 | dvb_dmx_swfilter(&fc->demux, buf, len); | ||
173 | } | ||
174 | EXPORT_SYMBOL(flexcop_pass_dmx_data); | ||
175 | |||
176 | void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no) | ||
177 | { | ||
178 | dvb_dmx_swfilter_packets(&fc->demux, buf, no); | ||
179 | } | ||
180 | EXPORT_SYMBOL(flexcop_pass_dmx_packets); | ||
181 | |||
182 | static void flexcop_reset(struct flexcop_device *fc) | ||
183 | { | ||
184 | flexcop_ibi_value v210, v204; | ||
185 | |||
186 | /* reset the flexcop itself */ | ||
187 | fc->write_ibi_reg(fc,ctrl_208,ibi_zero); | ||
188 | |||
189 | v210.raw = 0; | ||
190 | v210.sw_reset_210.reset_block_000 = 1; | ||
191 | v210.sw_reset_210.reset_block_100 = 1; | ||
192 | v210.sw_reset_210.reset_block_200 = 1; | ||
193 | v210.sw_reset_210.reset_block_300 = 1; | ||
194 | v210.sw_reset_210.reset_block_400 = 1; | ||
195 | v210.sw_reset_210.reset_block_500 = 1; | ||
196 | v210.sw_reset_210.reset_block_600 = 1; | ||
197 | v210.sw_reset_210.reset_block_700 = 1; | ||
198 | v210.sw_reset_210.Block_reset_enable = 0xb2; | ||
199 | v210.sw_reset_210.Special_controls = 0xc259; | ||
200 | fc->write_ibi_reg(fc,sw_reset_210,v210); | ||
201 | msleep(1); | ||
202 | |||
203 | /* reset the periphical devices */ | ||
204 | |||
205 | v204 = fc->read_ibi_reg(fc,misc_204); | ||
206 | v204.misc_204.Per_reset_sig = 0; | ||
207 | fc->write_ibi_reg(fc,misc_204,v204); | ||
208 | msleep(1); | ||
209 | v204.misc_204.Per_reset_sig = 1; | ||
210 | fc->write_ibi_reg(fc,misc_204,v204); | ||
211 | } | ||
212 | |||
213 | void flexcop_reset_block_300(struct flexcop_device *fc) | ||
214 | { | ||
215 | flexcop_ibi_value v208_save = fc->read_ibi_reg(fc, ctrl_208), | ||
216 | v210 = fc->read_ibi_reg(fc, sw_reset_210); | ||
217 | |||
218 | deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw); | ||
219 | fc->write_ibi_reg(fc,ctrl_208,ibi_zero); | ||
220 | |||
221 | v210.sw_reset_210.reset_block_300 = 1; | ||
222 | v210.sw_reset_210.Block_reset_enable = 0xb2; | ||
223 | |||
224 | fc->write_ibi_reg(fc,sw_reset_210,v210); | ||
225 | fc->write_ibi_reg(fc,ctrl_208,v208_save); | ||
226 | } | ||
227 | |||
228 | struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) | ||
229 | { | ||
230 | void *bus; | ||
231 | struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), | ||
232 | GFP_KERNEL); | ||
233 | if (!fc) { | ||
234 | err("no memory"); | ||
235 | return NULL; | ||
236 | } | ||
237 | |||
238 | bus = kzalloc(bus_specific_len, GFP_KERNEL); | ||
239 | if (!bus) { | ||
240 | err("no memory"); | ||
241 | kfree(fc); | ||
242 | return NULL; | ||
243 | } | ||
244 | |||
245 | fc->bus_specific = bus; | ||
246 | |||
247 | return fc; | ||
248 | } | ||
249 | EXPORT_SYMBOL(flexcop_device_kmalloc); | ||
250 | |||
251 | void flexcop_device_kfree(struct flexcop_device *fc) | ||
252 | { | ||
253 | kfree(fc->bus_specific); | ||
254 | kfree(fc); | ||
255 | } | ||
256 | EXPORT_SYMBOL(flexcop_device_kfree); | ||
257 | |||
258 | int flexcop_device_initialize(struct flexcop_device *fc) | ||
259 | { | ||
260 | int ret; | ||
261 | ibi_zero.raw = 0; | ||
262 | |||
263 | flexcop_reset(fc); | ||
264 | flexcop_determine_revision(fc); | ||
265 | flexcop_sram_init(fc); | ||
266 | flexcop_hw_filter_init(fc); | ||
267 | flexcop_smc_ctrl(fc, 0); | ||
268 | |||
269 | ret = flexcop_dvb_init(fc); | ||
270 | if (ret) | ||
271 | goto error; | ||
272 | |||
273 | /* i2c has to be done before doing EEProm stuff - | ||
274 | * because the EEProm is accessed via i2c */ | ||
275 | ret = flexcop_i2c_init(fc); | ||
276 | if (ret) | ||
277 | goto error; | ||
278 | |||
279 | /* do the MAC address reading after initializing the dvb_adapter */ | ||
280 | if (fc->get_mac_addr(fc, 0) == 0) { | ||
281 | u8 *b = fc->dvb_adapter.proposed_mac; | ||
282 | info("MAC address = %pM", b); | ||
283 | flexcop_set_mac_filter(fc,b); | ||
284 | flexcop_mac_filter_ctrl(fc,1); | ||
285 | } else | ||
286 | warn("reading of MAC address failed.\n"); | ||
287 | |||
288 | ret = flexcop_frontend_init(fc); | ||
289 | if (ret) | ||
290 | goto error; | ||
291 | |||
292 | flexcop_device_name(fc,"initialization of","complete"); | ||
293 | return 0; | ||
294 | |||
295 | error: | ||
296 | flexcop_device_exit(fc); | ||
297 | return ret; | ||
298 | } | ||
299 | EXPORT_SYMBOL(flexcop_device_initialize); | ||
300 | |||
301 | void flexcop_device_exit(struct flexcop_device *fc) | ||
302 | { | ||
303 | flexcop_frontend_exit(fc); | ||
304 | flexcop_i2c_exit(fc); | ||
305 | flexcop_dvb_exit(fc); | ||
306 | } | ||
307 | EXPORT_SYMBOL(flexcop_device_exit); | ||
308 | |||
309 | static int flexcop_module_init(void) | ||
310 | { | ||
311 | info(DRIVER_NAME " loaded successfully"); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static void flexcop_module_cleanup(void) | ||
316 | { | ||
317 | info(DRIVER_NAME " unloaded successfully"); | ||
318 | } | ||
319 | |||
320 | module_init(flexcop_module_init); | ||
321 | module_exit(flexcop_module_cleanup); | ||
322 | |||
323 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
324 | MODULE_DESCRIPTION(DRIVER_NAME); | ||
325 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/b2c2/flexcop.h b/drivers/media/common/b2c2/flexcop.h deleted file mode 100644 index 897b10c85ad..00000000000 --- a/drivers/media/common/b2c2/flexcop.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
3 | * flexcop.h - private header file for all flexcop-chip-source files | ||
4 | * see flexcop.c for copyright information | ||
5 | */ | ||
6 | #ifndef __FLEXCOP_H__ | ||
7 | #define __FLEXCOP_H___ | ||
8 | |||
9 | #define FC_LOG_PREFIX "b2c2-flexcop" | ||
10 | #include "flexcop-common.h" | ||
11 | |||
12 | extern int b2c2_flexcop_debug; | ||
13 | |||
14 | /* debug */ | ||
15 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | ||
16 | #define dprintk(level,args...) \ | ||
17 | do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0) | ||
18 | #else | ||
19 | #define dprintk(level,args...) | ||
20 | #endif | ||
21 | |||
22 | #define deb_info(args...) dprintk(0x01, args) | ||
23 | #define deb_tuner(args...) dprintk(0x02, args) | ||
24 | #define deb_i2c(args...) dprintk(0x04, args) | ||
25 | #define deb_ts(args...) dprintk(0x08, args) | ||
26 | #define deb_sram(args...) dprintk(0x10, args) | ||
27 | #define deb_rdump(args...) dprintk(0x20, args) | ||
28 | |||
29 | #endif | ||
diff --git a/drivers/media/common/b2c2/flexcop_ibi_value_be.h b/drivers/media/common/b2c2/flexcop_ibi_value_be.h deleted file mode 100644 index 8f64bdbd72b..00000000000 --- a/drivers/media/common/b2c2/flexcop_ibi_value_be.h +++ /dev/null | |||
@@ -1,455 +0,0 @@ | |||
1 | /* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
2 | * register descriptions | ||
3 | * see flexcop.c for copyright information | ||
4 | */ | ||
5 | /* This file is automatically generated, do not edit things here. */ | ||
6 | #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
7 | #define __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
8 | |||
9 | typedef union { | ||
10 | u32 raw; | ||
11 | |||
12 | struct { | ||
13 | u32 dma_address0 :30; | ||
14 | u32 dma_0No_update : 1; | ||
15 | u32 dma_0start : 1; | ||
16 | } dma_0x0; | ||
17 | |||
18 | struct { | ||
19 | u32 dma_addr_size :24; | ||
20 | u32 DMA_maxpackets : 8; | ||
21 | } dma_0x4_remap; | ||
22 | |||
23 | struct { | ||
24 | u32 dma_addr_size :24; | ||
25 | u32 unused : 1; | ||
26 | u32 dma1timer : 7; | ||
27 | } dma_0x4_read; | ||
28 | |||
29 | struct { | ||
30 | u32 dma_addr_size :24; | ||
31 | u32 dmatimer : 7; | ||
32 | u32 unused : 1; | ||
33 | } dma_0x4_write; | ||
34 | |||
35 | struct { | ||
36 | u32 dma_cur_addr :30; | ||
37 | u32 unused : 2; | ||
38 | } dma_0x8; | ||
39 | |||
40 | struct { | ||
41 | u32 dma_address1 :30; | ||
42 | u32 remap_enable : 1; | ||
43 | u32 dma_1start : 1; | ||
44 | } dma_0xc; | ||
45 | |||
46 | struct { | ||
47 | u32 st_done : 1; | ||
48 | u32 no_base_addr_ack_error : 1; | ||
49 | u32 twoWS_port_reg : 2; | ||
50 | u32 total_bytes : 2; | ||
51 | u32 twoWS_rw : 1; | ||
52 | u32 working_start : 1; | ||
53 | u32 data1_reg : 8; | ||
54 | u32 baseaddr : 8; | ||
55 | u32 reserved1 : 1; | ||
56 | u32 chipaddr : 7; | ||
57 | } tw_sm_c_100; | ||
58 | |||
59 | struct { | ||
60 | u32 unused : 6; | ||
61 | u32 force_stop : 1; | ||
62 | u32 exlicit_stops : 1; | ||
63 | u32 data4_reg : 8; | ||
64 | u32 data3_reg : 8; | ||
65 | u32 data2_reg : 8; | ||
66 | } tw_sm_c_104; | ||
67 | |||
68 | struct { | ||
69 | u32 reserved2 :19; | ||
70 | u32 tlo1 : 5; | ||
71 | u32 reserved1 : 2; | ||
72 | u32 thi1 : 6; | ||
73 | } tw_sm_c_108; | ||
74 | |||
75 | struct { | ||
76 | u32 reserved2 :19; | ||
77 | u32 tlo1 : 5; | ||
78 | u32 reserved1 : 2; | ||
79 | u32 thi1 : 6; | ||
80 | } tw_sm_c_10c; | ||
81 | |||
82 | struct { | ||
83 | u32 reserved2 :19; | ||
84 | u32 tlo1 : 5; | ||
85 | u32 reserved1 : 2; | ||
86 | u32 thi1 : 6; | ||
87 | } tw_sm_c_110; | ||
88 | |||
89 | struct { | ||
90 | u32 LNB_CTLPrescaler_sig : 2; | ||
91 | u32 LNB_CTLLowCount_sig :15; | ||
92 | u32 LNB_CTLHighCount_sig :15; | ||
93 | } lnb_switch_freq_200; | ||
94 | |||
95 | struct { | ||
96 | u32 Rev_N_sig_reserved2 : 1; | ||
97 | u32 Rev_N_sig_caps : 1; | ||
98 | u32 Rev_N_sig_reserved1 : 2; | ||
99 | u32 Rev_N_sig_revision_hi : 4; | ||
100 | u32 reserved :20; | ||
101 | u32 Per_reset_sig : 1; | ||
102 | u32 LNB_L_H_sig : 1; | ||
103 | u32 ACPI3_sig : 1; | ||
104 | u32 ACPI1_sig : 1; | ||
105 | } misc_204; | ||
106 | |||
107 | struct { | ||
108 | u32 unused : 9; | ||
109 | u32 Mailbox_from_V8_Enable_sig : 1; | ||
110 | u32 DMA2_Size_IRQ_Enable_sig : 1; | ||
111 | u32 DMA1_Size_IRQ_Enable_sig : 1; | ||
112 | u32 DMA2_Timer_Enable_sig : 1; | ||
113 | u32 DMA2_IRQ_Enable_sig : 1; | ||
114 | u32 DMA1_Timer_Enable_sig : 1; | ||
115 | u32 DMA1_IRQ_Enable_sig : 1; | ||
116 | u32 Rcv_Data_sig : 1; | ||
117 | u32 MAC_filter_Mode_sig : 1; | ||
118 | u32 Multi2_Enable_sig : 1; | ||
119 | u32 Per_CA_Enable_sig : 1; | ||
120 | u32 SMC_Enable_sig : 1; | ||
121 | u32 CA_Enable_sig : 1; | ||
122 | u32 WAN_CA_Enable_sig : 1; | ||
123 | u32 WAN_Enable_sig : 1; | ||
124 | u32 Mask_filter_sig : 1; | ||
125 | u32 Null_filter_sig : 1; | ||
126 | u32 ECM_filter_sig : 1; | ||
127 | u32 EMM_filter_sig : 1; | ||
128 | u32 PMT_filter_sig : 1; | ||
129 | u32 PCR_filter_sig : 1; | ||
130 | u32 Stream2_filter_sig : 1; | ||
131 | u32 Stream1_filter_sig : 1; | ||
132 | } ctrl_208; | ||
133 | |||
134 | struct { | ||
135 | u32 reserved :21; | ||
136 | u32 Transport_Error : 1; | ||
137 | u32 LLC_SNAP_FLAG_set : 1; | ||
138 | u32 Continuity_error_flag : 1; | ||
139 | u32 Data_receiver_error : 1; | ||
140 | u32 Mailbox_from_V8_Status_sig : 1; | ||
141 | u32 DMA2_Size_IRQ_Status : 1; | ||
142 | u32 DMA1_Size_IRQ_Status : 1; | ||
143 | u32 DMA2_Timer_Status : 1; | ||
144 | u32 DMA2_IRQ_Status : 1; | ||
145 | u32 DMA1_Timer_Status : 1; | ||
146 | u32 DMA1_IRQ_Status : 1; | ||
147 | } irq_20c; | ||
148 | |||
149 | struct { | ||
150 | u32 Special_controls :16; | ||
151 | u32 Block_reset_enable : 8; | ||
152 | u32 reset_block_700 : 1; | ||
153 | u32 reset_block_600 : 1; | ||
154 | u32 reset_block_500 : 1; | ||
155 | u32 reset_block_400 : 1; | ||
156 | u32 reset_block_300 : 1; | ||
157 | u32 reset_block_200 : 1; | ||
158 | u32 reset_block_100 : 1; | ||
159 | u32 reset_block_000 : 1; | ||
160 | } sw_reset_210; | ||
161 | |||
162 | struct { | ||
163 | u32 unused2 :20; | ||
164 | u32 polarity_PS_ERR_sig : 1; | ||
165 | u32 polarity_PS_SYNC_sig : 1; | ||
166 | u32 polarity_PS_VALID_sig : 1; | ||
167 | u32 polarity_PS_CLK_sig : 1; | ||
168 | u32 unused1 : 3; | ||
169 | u32 s2p_sel_sig : 1; | ||
170 | u32 section_pkg_enable_sig : 1; | ||
171 | u32 halt_V8_sig : 1; | ||
172 | u32 v2WS_oe_sig : 1; | ||
173 | u32 vuart_oe_sig : 1; | ||
174 | } misc_214; | ||
175 | |||
176 | struct { | ||
177 | u32 Mailbox_from_V8 :32; | ||
178 | } mbox_v8_to_host_218; | ||
179 | |||
180 | struct { | ||
181 | u32 sysramaccess_busmuster : 1; | ||
182 | u32 sysramaccess_write : 1; | ||
183 | u32 unused : 7; | ||
184 | u32 sysramaccess_addr :15; | ||
185 | u32 sysramaccess_data : 8; | ||
186 | } mbox_host_to_v8_21c; | ||
187 | |||
188 | struct { | ||
189 | u32 debug_fifo_problem : 1; | ||
190 | u32 debug_flag_write_status00 : 1; | ||
191 | u32 Stream2_trans : 1; | ||
192 | u32 Stream2_PID :13; | ||
193 | u32 debug_flag_pid_saved : 1; | ||
194 | u32 MAC_Multicast_filter : 1; | ||
195 | u32 Stream1_trans : 1; | ||
196 | u32 Stream1_PID :13; | ||
197 | } pid_filter_300; | ||
198 | |||
199 | struct { | ||
200 | u32 reserved : 2; | ||
201 | u32 PMT_trans : 1; | ||
202 | u32 PMT_PID :13; | ||
203 | u32 debug_overrun2 : 1; | ||
204 | u32 debug_overrun3 : 1; | ||
205 | u32 PCR_trans : 1; | ||
206 | u32 PCR_PID :13; | ||
207 | } pid_filter_304; | ||
208 | |||
209 | struct { | ||
210 | u32 reserved : 2; | ||
211 | u32 ECM_trans : 1; | ||
212 | u32 ECM_PID :13; | ||
213 | u32 EMM_filter_6 : 1; | ||
214 | u32 EMM_filter_4 : 1; | ||
215 | u32 EMM_trans : 1; | ||
216 | u32 EMM_PID :13; | ||
217 | } pid_filter_308; | ||
218 | |||
219 | struct { | ||
220 | u32 unused2 : 3; | ||
221 | u32 Group_mask :13; | ||
222 | u32 unused1 : 2; | ||
223 | u32 Group_trans : 1; | ||
224 | u32 Group_PID :13; | ||
225 | } pid_filter_30c_ext_ind_0_7; | ||
226 | |||
227 | struct { | ||
228 | u32 unused :15; | ||
229 | u32 net_master_read :17; | ||
230 | } pid_filter_30c_ext_ind_1; | ||
231 | |||
232 | struct { | ||
233 | u32 unused :15; | ||
234 | u32 net_master_write :17; | ||
235 | } pid_filter_30c_ext_ind_2; | ||
236 | |||
237 | struct { | ||
238 | u32 unused :15; | ||
239 | u32 next_net_master_write :17; | ||
240 | } pid_filter_30c_ext_ind_3; | ||
241 | |||
242 | struct { | ||
243 | u32 reserved2 : 5; | ||
244 | u32 stack_read :10; | ||
245 | u32 reserved1 : 6; | ||
246 | u32 state_write :10; | ||
247 | u32 unused1 : 1; | ||
248 | } pid_filter_30c_ext_ind_4; | ||
249 | |||
250 | struct { | ||
251 | u32 unused :22; | ||
252 | u32 stack_cnt :10; | ||
253 | } pid_filter_30c_ext_ind_5; | ||
254 | |||
255 | struct { | ||
256 | u32 unused : 4; | ||
257 | u32 data_size_reg :12; | ||
258 | u32 write_status4 : 2; | ||
259 | u32 write_status1 : 2; | ||
260 | u32 pid_fsm_save_reg300 : 2; | ||
261 | u32 pid_fsm_save_reg4 : 2; | ||
262 | u32 pid_fsm_save_reg3 : 2; | ||
263 | u32 pid_fsm_save_reg2 : 2; | ||
264 | u32 pid_fsm_save_reg1 : 2; | ||
265 | u32 pid_fsm_save_reg0 : 2; | ||
266 | } pid_filter_30c_ext_ind_6; | ||
267 | |||
268 | struct { | ||
269 | u32 unused :22; | ||
270 | u32 pass_alltables : 1; | ||
271 | u32 AB_select : 1; | ||
272 | u32 extra_index_reg : 3; | ||
273 | u32 index_reg : 5; | ||
274 | } index_reg_310; | ||
275 | |||
276 | struct { | ||
277 | u32 reserved :17; | ||
278 | u32 PID_enable_bit : 1; | ||
279 | u32 PID_trans : 1; | ||
280 | u32 PID :13; | ||
281 | } pid_n_reg_314; | ||
282 | |||
283 | struct { | ||
284 | u32 reserved : 6; | ||
285 | u32 HighAB_bit : 1; | ||
286 | u32 Enable_bit : 1; | ||
287 | u32 A6_byte : 8; | ||
288 | u32 A5_byte : 8; | ||
289 | u32 A4_byte : 8; | ||
290 | } mac_low_reg_318; | ||
291 | |||
292 | struct { | ||
293 | u32 reserved : 8; | ||
294 | u32 A3_byte : 8; | ||
295 | u32 A2_byte : 8; | ||
296 | u32 A1_byte : 8; | ||
297 | } mac_high_reg_31c; | ||
298 | |||
299 | struct { | ||
300 | u32 data_Tag_ID :16; | ||
301 | u32 reserved :16; | ||
302 | } data_tag_400; | ||
303 | |||
304 | struct { | ||
305 | u32 Card_IDbyte3 : 8; | ||
306 | u32 Card_IDbyte4 : 8; | ||
307 | u32 Card_IDbyte5 : 8; | ||
308 | u32 Card_IDbyte6 : 8; | ||
309 | } card_id_408; | ||
310 | |||
311 | struct { | ||
312 | u32 Card_IDbyte1 : 8; | ||
313 | u32 Card_IDbyte2 : 8; | ||
314 | } card_id_40c; | ||
315 | |||
316 | struct { | ||
317 | u32 MAC6 : 8; | ||
318 | u32 MAC3 : 8; | ||
319 | u32 MAC2 : 8; | ||
320 | u32 MAC1 : 8; | ||
321 | } mac_address_418; | ||
322 | |||
323 | struct { | ||
324 | u32 reserved :16; | ||
325 | u32 MAC8 : 8; | ||
326 | u32 MAC7 : 8; | ||
327 | } mac_address_41c; | ||
328 | |||
329 | struct { | ||
330 | u32 reserved :21; | ||
331 | u32 txbuffempty : 1; | ||
332 | u32 ReceiveByteFrameError : 1; | ||
333 | u32 ReceiveDataReady : 1; | ||
334 | u32 transmitter_data_byte : 8; | ||
335 | } ci_600; | ||
336 | |||
337 | struct { | ||
338 | u32 pi_component_reg : 3; | ||
339 | u32 pi_rw : 1; | ||
340 | u32 pi_ha :20; | ||
341 | u32 pi_d : 8; | ||
342 | } pi_604; | ||
343 | |||
344 | struct { | ||
345 | u32 pi_busy_n : 1; | ||
346 | u32 pi_wait_n : 1; | ||
347 | u32 pi_timeout_status : 1; | ||
348 | u32 pi_CiMax_IRQ_n : 1; | ||
349 | u32 config_cclk : 1; | ||
350 | u32 config_cs_n : 1; | ||
351 | u32 config_wr_n : 1; | ||
352 | u32 config_Prog_n : 1; | ||
353 | u32 config_Init_stat : 1; | ||
354 | u32 config_Done_stat : 1; | ||
355 | u32 pcmcia_b_mod_pwr_n : 1; | ||
356 | u32 pcmcia_a_mod_pwr_n : 1; | ||
357 | u32 reserved : 3; | ||
358 | u32 Timer_addr : 5; | ||
359 | u32 unused : 1; | ||
360 | u32 timer_data : 7; | ||
361 | u32 Timer_Load_req : 1; | ||
362 | u32 Timer_Read_req : 1; | ||
363 | u32 oncecycle_read : 1; | ||
364 | u32 serialReset : 1; | ||
365 | } pi_608; | ||
366 | |||
367 | struct { | ||
368 | u32 reserved : 6; | ||
369 | u32 rw_flag : 1; | ||
370 | u32 dvb_en : 1; | ||
371 | u32 key_array_row : 5; | ||
372 | u32 key_array_col : 3; | ||
373 | u32 key_code : 2; | ||
374 | u32 key_enable : 1; | ||
375 | u32 PID :13; | ||
376 | } dvb_reg_60c; | ||
377 | |||
378 | struct { | ||
379 | u32 start_sram_ibi : 1; | ||
380 | u32 reserved2 : 1; | ||
381 | u32 ce_pin_reg : 1; | ||
382 | u32 oe_pin_reg : 1; | ||
383 | u32 reserved1 : 3; | ||
384 | u32 sc_xfer_bit : 1; | ||
385 | u32 sram_data : 8; | ||
386 | u32 sram_rw : 1; | ||
387 | u32 sram_addr :15; | ||
388 | } sram_ctrl_reg_700; | ||
389 | |||
390 | struct { | ||
391 | u32 net_addr_write :16; | ||
392 | u32 net_addr_read :16; | ||
393 | } net_buf_reg_704; | ||
394 | |||
395 | struct { | ||
396 | u32 cai_cnt : 4; | ||
397 | u32 reserved2 : 6; | ||
398 | u32 cai_write :11; | ||
399 | u32 reserved1 : 5; | ||
400 | u32 cai_read :11; | ||
401 | } cai_buf_reg_708; | ||
402 | |||
403 | struct { | ||
404 | u32 cao_cnt : 4; | ||
405 | u32 reserved2 : 6; | ||
406 | u32 cap_write :11; | ||
407 | u32 reserved1 : 5; | ||
408 | u32 cao_read :11; | ||
409 | } cao_buf_reg_70c; | ||
410 | |||
411 | struct { | ||
412 | u32 media_cnt : 4; | ||
413 | u32 reserved2 : 6; | ||
414 | u32 media_write :11; | ||
415 | u32 reserved1 : 5; | ||
416 | u32 media_read :11; | ||
417 | } media_buf_reg_710; | ||
418 | |||
419 | struct { | ||
420 | u32 reserved :17; | ||
421 | u32 ctrl_maximumfill : 1; | ||
422 | u32 ctrl_sramdma : 1; | ||
423 | u32 ctrl_usb_wan : 1; | ||
424 | u32 cao_ovflow_error : 1; | ||
425 | u32 cai_ovflow_error : 1; | ||
426 | u32 media_ovflow_error : 1; | ||
427 | u32 net_ovflow_error : 1; | ||
428 | u32 MEDIA_Dest : 2; | ||
429 | u32 CAO_Dest : 2; | ||
430 | u32 CAI_Dest : 2; | ||
431 | u32 NET_Dest : 2; | ||
432 | } sram_dest_reg_714; | ||
433 | |||
434 | struct { | ||
435 | u32 reserved3 :11; | ||
436 | u32 net_addr_write : 1; | ||
437 | u32 reserved2 : 3; | ||
438 | u32 net_addr_read : 1; | ||
439 | u32 reserved1 : 4; | ||
440 | u32 net_cnt :12; | ||
441 | } net_buf_reg_718; | ||
442 | |||
443 | struct { | ||
444 | u32 reserved3 : 4; | ||
445 | u32 wan_pkt_frame : 4; | ||
446 | u32 reserved2 : 4; | ||
447 | u32 sram_memmap : 2; | ||
448 | u32 sram_chip : 2; | ||
449 | u32 wan_wait_state : 8; | ||
450 | u32 reserved1 : 6; | ||
451 | u32 wan_speed_sig : 2; | ||
452 | } wan_ctrl_reg_71c; | ||
453 | } flexcop_ibi_value; | ||
454 | |||
455 | #endif | ||
diff --git a/drivers/media/common/b2c2/flexcop_ibi_value_le.h b/drivers/media/common/b2c2/flexcop_ibi_value_le.h deleted file mode 100644 index c75830d7d94..00000000000 --- a/drivers/media/common/b2c2/flexcop_ibi_value_le.h +++ /dev/null | |||
@@ -1,455 +0,0 @@ | |||
1 | /* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | ||
2 | * register descriptions | ||
3 | * see flexcop.c for copyright information | ||
4 | */ | ||
5 | /* This file is automatically generated, do not edit things here. */ | ||
6 | #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
7 | #define __FLEXCOP_IBI_VALUE_INCLUDED__ | ||
8 | |||
9 | typedef union { | ||
10 | u32 raw; | ||
11 | |||
12 | struct { | ||
13 | u32 dma_0start : 1; | ||
14 | u32 dma_0No_update : 1; | ||
15 | u32 dma_address0 :30; | ||
16 | } dma_0x0; | ||
17 | |||
18 | struct { | ||
19 | u32 DMA_maxpackets : 8; | ||
20 | u32 dma_addr_size :24; | ||
21 | } dma_0x4_remap; | ||
22 | |||
23 | struct { | ||
24 | u32 dma1timer : 7; | ||
25 | u32 unused : 1; | ||
26 | u32 dma_addr_size :24; | ||
27 | } dma_0x4_read; | ||
28 | |||
29 | struct { | ||
30 | u32 unused : 1; | ||
31 | u32 dmatimer : 7; | ||
32 | u32 dma_addr_size :24; | ||
33 | } dma_0x4_write; | ||
34 | |||
35 | struct { | ||
36 | u32 unused : 2; | ||
37 | u32 dma_cur_addr :30; | ||
38 | } dma_0x8; | ||
39 | |||
40 | struct { | ||
41 | u32 dma_1start : 1; | ||
42 | u32 remap_enable : 1; | ||
43 | u32 dma_address1 :30; | ||
44 | } dma_0xc; | ||
45 | |||
46 | struct { | ||
47 | u32 chipaddr : 7; | ||
48 | u32 reserved1 : 1; | ||
49 | u32 baseaddr : 8; | ||
50 | u32 data1_reg : 8; | ||
51 | u32 working_start : 1; | ||
52 | u32 twoWS_rw : 1; | ||
53 | u32 total_bytes : 2; | ||
54 | u32 twoWS_port_reg : 2; | ||
55 | u32 no_base_addr_ack_error : 1; | ||
56 | u32 st_done : 1; | ||
57 | } tw_sm_c_100; | ||
58 | |||
59 | struct { | ||
60 | u32 data2_reg : 8; | ||
61 | u32 data3_reg : 8; | ||
62 | u32 data4_reg : 8; | ||
63 | u32 exlicit_stops : 1; | ||
64 | u32 force_stop : 1; | ||
65 | u32 unused : 6; | ||
66 | } tw_sm_c_104; | ||
67 | |||
68 | struct { | ||
69 | u32 thi1 : 6; | ||
70 | u32 reserved1 : 2; | ||
71 | u32 tlo1 : 5; | ||
72 | u32 reserved2 :19; | ||
73 | } tw_sm_c_108; | ||
74 | |||
75 | struct { | ||
76 | u32 thi1 : 6; | ||
77 | u32 reserved1 : 2; | ||
78 | u32 tlo1 : 5; | ||
79 | u32 reserved2 :19; | ||
80 | } tw_sm_c_10c; | ||
81 | |||
82 | struct { | ||
83 | u32 thi1 : 6; | ||
84 | u32 reserved1 : 2; | ||
85 | u32 tlo1 : 5; | ||
86 | u32 reserved2 :19; | ||
87 | } tw_sm_c_110; | ||
88 | |||
89 | struct { | ||
90 | u32 LNB_CTLHighCount_sig :15; | ||
91 | u32 LNB_CTLLowCount_sig :15; | ||
92 | u32 LNB_CTLPrescaler_sig : 2; | ||
93 | } lnb_switch_freq_200; | ||
94 | |||
95 | struct { | ||
96 | u32 ACPI1_sig : 1; | ||
97 | u32 ACPI3_sig : 1; | ||
98 | u32 LNB_L_H_sig : 1; | ||
99 | u32 Per_reset_sig : 1; | ||
100 | u32 reserved :20; | ||
101 | u32 Rev_N_sig_revision_hi : 4; | ||
102 | u32 Rev_N_sig_reserved1 : 2; | ||
103 | u32 Rev_N_sig_caps : 1; | ||
104 | u32 Rev_N_sig_reserved2 : 1; | ||
105 | } misc_204; | ||
106 | |||
107 | struct { | ||
108 | u32 Stream1_filter_sig : 1; | ||
109 | u32 Stream2_filter_sig : 1; | ||
110 | u32 PCR_filter_sig : 1; | ||
111 | u32 PMT_filter_sig : 1; | ||
112 | u32 EMM_filter_sig : 1; | ||
113 | u32 ECM_filter_sig : 1; | ||
114 | u32 Null_filter_sig : 1; | ||
115 | u32 Mask_filter_sig : 1; | ||
116 | u32 WAN_Enable_sig : 1; | ||
117 | u32 WAN_CA_Enable_sig : 1; | ||
118 | u32 CA_Enable_sig : 1; | ||
119 | u32 SMC_Enable_sig : 1; | ||
120 | u32 Per_CA_Enable_sig : 1; | ||
121 | u32 Multi2_Enable_sig : 1; | ||
122 | u32 MAC_filter_Mode_sig : 1; | ||
123 | u32 Rcv_Data_sig : 1; | ||
124 | u32 DMA1_IRQ_Enable_sig : 1; | ||
125 | u32 DMA1_Timer_Enable_sig : 1; | ||
126 | u32 DMA2_IRQ_Enable_sig : 1; | ||
127 | u32 DMA2_Timer_Enable_sig : 1; | ||
128 | u32 DMA1_Size_IRQ_Enable_sig : 1; | ||
129 | u32 DMA2_Size_IRQ_Enable_sig : 1; | ||
130 | u32 Mailbox_from_V8_Enable_sig : 1; | ||
131 | u32 unused : 9; | ||
132 | } ctrl_208; | ||
133 | |||
134 | struct { | ||
135 | u32 DMA1_IRQ_Status : 1; | ||
136 | u32 DMA1_Timer_Status : 1; | ||
137 | u32 DMA2_IRQ_Status : 1; | ||
138 | u32 DMA2_Timer_Status : 1; | ||
139 | u32 DMA1_Size_IRQ_Status : 1; | ||
140 | u32 DMA2_Size_IRQ_Status : 1; | ||
141 | u32 Mailbox_from_V8_Status_sig : 1; | ||
142 | u32 Data_receiver_error : 1; | ||
143 | u32 Continuity_error_flag : 1; | ||
144 | u32 LLC_SNAP_FLAG_set : 1; | ||
145 | u32 Transport_Error : 1; | ||
146 | u32 reserved :21; | ||
147 | } irq_20c; | ||
148 | |||
149 | struct { | ||
150 | u32 reset_block_000 : 1; | ||
151 | u32 reset_block_100 : 1; | ||
152 | u32 reset_block_200 : 1; | ||
153 | u32 reset_block_300 : 1; | ||
154 | u32 reset_block_400 : 1; | ||
155 | u32 reset_block_500 : 1; | ||
156 | u32 reset_block_600 : 1; | ||
157 | u32 reset_block_700 : 1; | ||
158 | u32 Block_reset_enable : 8; | ||
159 | u32 Special_controls :16; | ||
160 | } sw_reset_210; | ||
161 | |||
162 | struct { | ||
163 | u32 vuart_oe_sig : 1; | ||
164 | u32 v2WS_oe_sig : 1; | ||
165 | u32 halt_V8_sig : 1; | ||
166 | u32 section_pkg_enable_sig : 1; | ||
167 | u32 s2p_sel_sig : 1; | ||
168 | u32 unused1 : 3; | ||
169 | u32 polarity_PS_CLK_sig : 1; | ||
170 | u32 polarity_PS_VALID_sig : 1; | ||
171 | u32 polarity_PS_SYNC_sig : 1; | ||
172 | u32 polarity_PS_ERR_sig : 1; | ||
173 | u32 unused2 :20; | ||
174 | } misc_214; | ||
175 | |||
176 | struct { | ||
177 | u32 Mailbox_from_V8 :32; | ||
178 | } mbox_v8_to_host_218; | ||
179 | |||
180 | struct { | ||
181 | u32 sysramaccess_data : 8; | ||
182 | u32 sysramaccess_addr :15; | ||
183 | u32 unused : 7; | ||
184 | u32 sysramaccess_write : 1; | ||
185 | u32 sysramaccess_busmuster : 1; | ||
186 | } mbox_host_to_v8_21c; | ||
187 | |||
188 | struct { | ||
189 | u32 Stream1_PID :13; | ||
190 | u32 Stream1_trans : 1; | ||
191 | u32 MAC_Multicast_filter : 1; | ||
192 | u32 debug_flag_pid_saved : 1; | ||
193 | u32 Stream2_PID :13; | ||
194 | u32 Stream2_trans : 1; | ||
195 | u32 debug_flag_write_status00 : 1; | ||
196 | u32 debug_fifo_problem : 1; | ||
197 | } pid_filter_300; | ||
198 | |||
199 | struct { | ||
200 | u32 PCR_PID :13; | ||
201 | u32 PCR_trans : 1; | ||
202 | u32 debug_overrun3 : 1; | ||
203 | u32 debug_overrun2 : 1; | ||
204 | u32 PMT_PID :13; | ||
205 | u32 PMT_trans : 1; | ||
206 | u32 reserved : 2; | ||
207 | } pid_filter_304; | ||
208 | |||
209 | struct { | ||
210 | u32 EMM_PID :13; | ||
211 | u32 EMM_trans : 1; | ||
212 | u32 EMM_filter_4 : 1; | ||
213 | u32 EMM_filter_6 : 1; | ||
214 | u32 ECM_PID :13; | ||
215 | u32 ECM_trans : 1; | ||
216 | u32 reserved : 2; | ||
217 | } pid_filter_308; | ||
218 | |||
219 | struct { | ||
220 | u32 Group_PID :13; | ||
221 | u32 Group_trans : 1; | ||
222 | u32 unused1 : 2; | ||
223 | u32 Group_mask :13; | ||
224 | u32 unused2 : 3; | ||
225 | } pid_filter_30c_ext_ind_0_7; | ||
226 | |||
227 | struct { | ||
228 | u32 net_master_read :17; | ||
229 | u32 unused :15; | ||
230 | } pid_filter_30c_ext_ind_1; | ||
231 | |||
232 | struct { | ||
233 | u32 net_master_write :17; | ||
234 | u32 unused :15; | ||
235 | } pid_filter_30c_ext_ind_2; | ||
236 | |||
237 | struct { | ||
238 | u32 next_net_master_write :17; | ||
239 | u32 unused :15; | ||
240 | } pid_filter_30c_ext_ind_3; | ||
241 | |||
242 | struct { | ||
243 | u32 unused1 : 1; | ||
244 | u32 state_write :10; | ||
245 | u32 reserved1 : 6; | ||
246 | u32 stack_read :10; | ||
247 | u32 reserved2 : 5; | ||
248 | } pid_filter_30c_ext_ind_4; | ||
249 | |||
250 | struct { | ||
251 | u32 stack_cnt :10; | ||
252 | u32 unused :22; | ||
253 | } pid_filter_30c_ext_ind_5; | ||
254 | |||
255 | struct { | ||
256 | u32 pid_fsm_save_reg0 : 2; | ||
257 | u32 pid_fsm_save_reg1 : 2; | ||
258 | u32 pid_fsm_save_reg2 : 2; | ||
259 | u32 pid_fsm_save_reg3 : 2; | ||
260 | u32 pid_fsm_save_reg4 : 2; | ||
261 | u32 pid_fsm_save_reg300 : 2; | ||
262 | u32 write_status1 : 2; | ||
263 | u32 write_status4 : 2; | ||
264 | u32 data_size_reg :12; | ||
265 | u32 unused : 4; | ||
266 | } pid_filter_30c_ext_ind_6; | ||
267 | |||
268 | struct { | ||
269 | u32 index_reg : 5; | ||
270 | u32 extra_index_reg : 3; | ||
271 | u32 AB_select : 1; | ||
272 | u32 pass_alltables : 1; | ||
273 | u32 unused :22; | ||
274 | } index_reg_310; | ||
275 | |||
276 | struct { | ||
277 | u32 PID :13; | ||
278 | u32 PID_trans : 1; | ||
279 | u32 PID_enable_bit : 1; | ||
280 | u32 reserved :17; | ||
281 | } pid_n_reg_314; | ||
282 | |||
283 | struct { | ||
284 | u32 A4_byte : 8; | ||
285 | u32 A5_byte : 8; | ||
286 | u32 A6_byte : 8; | ||
287 | u32 Enable_bit : 1; | ||
288 | u32 HighAB_bit : 1; | ||
289 | u32 reserved : 6; | ||
290 | } mac_low_reg_318; | ||
291 | |||
292 | struct { | ||
293 | u32 A1_byte : 8; | ||
294 | u32 A2_byte : 8; | ||
295 | u32 A3_byte : 8; | ||
296 | u32 reserved : 8; | ||
297 | } mac_high_reg_31c; | ||
298 | |||
299 | struct { | ||
300 | u32 reserved :16; | ||
301 | u32 data_Tag_ID :16; | ||
302 | } data_tag_400; | ||
303 | |||
304 | struct { | ||
305 | u32 Card_IDbyte6 : 8; | ||
306 | u32 Card_IDbyte5 : 8; | ||
307 | u32 Card_IDbyte4 : 8; | ||
308 | u32 Card_IDbyte3 : 8; | ||
309 | } card_id_408; | ||
310 | |||
311 | struct { | ||
312 | u32 Card_IDbyte2 : 8; | ||
313 | u32 Card_IDbyte1 : 8; | ||
314 | } card_id_40c; | ||
315 | |||
316 | struct { | ||
317 | u32 MAC1 : 8; | ||
318 | u32 MAC2 : 8; | ||
319 | u32 MAC3 : 8; | ||
320 | u32 MAC6 : 8; | ||
321 | } mac_address_418; | ||
322 | |||
323 | struct { | ||
324 | u32 MAC7 : 8; | ||
325 | u32 MAC8 : 8; | ||
326 | u32 reserved :16; | ||
327 | } mac_address_41c; | ||
328 | |||
329 | struct { | ||
330 | u32 transmitter_data_byte : 8; | ||
331 | u32 ReceiveDataReady : 1; | ||
332 | u32 ReceiveByteFrameError : 1; | ||
333 | u32 txbuffempty : 1; | ||
334 | u32 reserved :21; | ||
335 | } ci_600; | ||
336 | |||
337 | struct { | ||
338 | u32 pi_d : 8; | ||
339 | u32 pi_ha :20; | ||
340 | u32 pi_rw : 1; | ||
341 | u32 pi_component_reg : 3; | ||
342 | } pi_604; | ||
343 | |||
344 | struct { | ||
345 | u32 serialReset : 1; | ||
346 | u32 oncecycle_read : 1; | ||
347 | u32 Timer_Read_req : 1; | ||
348 | u32 Timer_Load_req : 1; | ||
349 | u32 timer_data : 7; | ||
350 | u32 unused : 1; | ||
351 | u32 Timer_addr : 5; | ||
352 | u32 reserved : 3; | ||
353 | u32 pcmcia_a_mod_pwr_n : 1; | ||
354 | u32 pcmcia_b_mod_pwr_n : 1; | ||
355 | u32 config_Done_stat : 1; | ||
356 | u32 config_Init_stat : 1; | ||
357 | u32 config_Prog_n : 1; | ||
358 | u32 config_wr_n : 1; | ||
359 | u32 config_cs_n : 1; | ||
360 | u32 config_cclk : 1; | ||
361 | u32 pi_CiMax_IRQ_n : 1; | ||
362 | u32 pi_timeout_status : 1; | ||
363 | u32 pi_wait_n : 1; | ||
364 | u32 pi_busy_n : 1; | ||
365 | } pi_608; | ||
366 | |||
367 | struct { | ||
368 | u32 PID :13; | ||
369 | u32 key_enable : 1; | ||
370 | u32 key_code : 2; | ||
371 | u32 key_array_col : 3; | ||
372 | u32 key_array_row : 5; | ||
373 | u32 dvb_en : 1; | ||
374 | u32 rw_flag : 1; | ||
375 | u32 reserved : 6; | ||
376 | } dvb_reg_60c; | ||
377 | |||
378 | struct { | ||
379 | u32 sram_addr :15; | ||
380 | u32 sram_rw : 1; | ||
381 | u32 sram_data : 8; | ||
382 | u32 sc_xfer_bit : 1; | ||
383 | u32 reserved1 : 3; | ||
384 | u32 oe_pin_reg : 1; | ||
385 | u32 ce_pin_reg : 1; | ||
386 | u32 reserved2 : 1; | ||
387 | u32 start_sram_ibi : 1; | ||
388 | } sram_ctrl_reg_700; | ||
389 | |||
390 | struct { | ||
391 | u32 net_addr_read :16; | ||
392 | u32 net_addr_write :16; | ||
393 | } net_buf_reg_704; | ||
394 | |||
395 | struct { | ||
396 | u32 cai_read :11; | ||
397 | u32 reserved1 : 5; | ||
398 | u32 cai_write :11; | ||
399 | u32 reserved2 : 6; | ||
400 | u32 cai_cnt : 4; | ||
401 | } cai_buf_reg_708; | ||
402 | |||
403 | struct { | ||
404 | u32 cao_read :11; | ||
405 | u32 reserved1 : 5; | ||
406 | u32 cap_write :11; | ||
407 | u32 reserved2 : 6; | ||
408 | u32 cao_cnt : 4; | ||
409 | } cao_buf_reg_70c; | ||
410 | |||
411 | struct { | ||
412 | u32 media_read :11; | ||
413 | u32 reserved1 : 5; | ||
414 | u32 media_write :11; | ||
415 | u32 reserved2 : 6; | ||
416 | u32 media_cnt : 4; | ||
417 | } media_buf_reg_710; | ||
418 | |||
419 | struct { | ||
420 | u32 NET_Dest : 2; | ||
421 | u32 CAI_Dest : 2; | ||
422 | u32 CAO_Dest : 2; | ||
423 | u32 MEDIA_Dest : 2; | ||
424 | u32 net_ovflow_error : 1; | ||
425 | u32 media_ovflow_error : 1; | ||
426 | u32 cai_ovflow_error : 1; | ||
427 | u32 cao_ovflow_error : 1; | ||
428 | u32 ctrl_usb_wan : 1; | ||
429 | u32 ctrl_sramdma : 1; | ||
430 | u32 ctrl_maximumfill : 1; | ||
431 | u32 reserved :17; | ||
432 | } sram_dest_reg_714; | ||
433 | |||
434 | struct { | ||
435 | u32 net_cnt :12; | ||
436 | u32 reserved1 : 4; | ||
437 | u32 net_addr_read : 1; | ||
438 | u32 reserved2 : 3; | ||
439 | u32 net_addr_write : 1; | ||
440 | u32 reserved3 :11; | ||
441 | } net_buf_reg_718; | ||
442 | |||
443 | struct { | ||
444 | u32 wan_speed_sig : 2; | ||
445 | u32 reserved1 : 6; | ||
446 | u32 wan_wait_state : 8; | ||
447 | u32 sram_chip : 2; | ||
448 | u32 sram_memmap : 2; | ||
449 | u32 reserved2 : 4; | ||
450 | u32 wan_pkt_frame : 4; | ||
451 | u32 reserved3 : 4; | ||
452 | } wan_ctrl_reg_71c; | ||
453 | } flexcop_ibi_value; | ||
454 | |||
455 | #endif | ||
diff --git a/drivers/media/common/saa7146/Kconfig b/drivers/media/common/saa7146/Kconfig deleted file mode 100644 index 769c6f8142d..00000000000 --- a/drivers/media/common/saa7146/Kconfig +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | config VIDEO_SAA7146 | ||
2 | tristate | ||
3 | depends on I2C && PCI | ||
4 | |||
5 | config VIDEO_SAA7146_VV | ||
6 | tristate | ||
7 | depends on VIDEO_V4L2 | ||
8 | select VIDEOBUF_DMA_SG | ||
9 | select VIDEO_SAA7146 | ||
diff --git a/drivers/media/common/saa7146/Makefile b/drivers/media/common/saa7146/Makefile deleted file mode 100644 index 3219b00a877..00000000000 --- a/drivers/media/common/saa7146/Makefile +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | saa7146-objs := saa7146_i2c.o saa7146_core.o | ||
2 | saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o | ||
3 | |||
4 | obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o | ||
5 | obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o | ||
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c deleted file mode 100644 index bb6ee5191eb..00000000000 --- a/drivers/media/common/saa7146/saa7146_core.c +++ /dev/null | |||
@@ -1,592 +0,0 @@ | |||
1 | /* | ||
2 | saa7146.o - driver for generic saa7146-based hardware | ||
3 | |||
4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
22 | |||
23 | #include <media/saa7146.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | static int saa7146_num; | ||
27 | |||
28 | unsigned int saa7146_debug; | ||
29 | |||
30 | module_param(saa7146_debug, uint, 0644); | ||
31 | MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)"); | ||
32 | |||
33 | #if 0 | ||
34 | static void dump_registers(struct saa7146_dev* dev) | ||
35 | { | ||
36 | int i = 0; | ||
37 | |||
38 | pr_info(" @ %li jiffies:\n", jiffies); | ||
39 | for (i = 0; i <= 0x148; i += 4) | ||
40 | pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i)); | ||
41 | } | ||
42 | #endif | ||
43 | |||
44 | /**************************************************************************** | ||
45 | * gpio and debi helper functions | ||
46 | ****************************************************************************/ | ||
47 | |||
48 | void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) | ||
49 | { | ||
50 | u32 value = 0; | ||
51 | |||
52 | BUG_ON(port > 3); | ||
53 | |||
54 | value = saa7146_read(dev, GPIO_CTRL); | ||
55 | value &= ~(0xff << (8*port)); | ||
56 | value |= (data << (8*port)); | ||
57 | saa7146_write(dev, GPIO_CTRL, value); | ||
58 | } | ||
59 | |||
60 | /* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ | ||
61 | static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev, | ||
62 | unsigned long us1, unsigned long us2) | ||
63 | { | ||
64 | unsigned long timeout; | ||
65 | int err; | ||
66 | |||
67 | /* wait for registers to be programmed */ | ||
68 | timeout = jiffies + usecs_to_jiffies(us1); | ||
69 | while (1) { | ||
70 | err = time_after(jiffies, timeout); | ||
71 | if (saa7146_read(dev, MC2) & 2) | ||
72 | break; | ||
73 | if (err) { | ||
74 | pr_err("%s: %s timed out while waiting for registers getting programmed\n", | ||
75 | dev->name, __func__); | ||
76 | return -ETIMEDOUT; | ||
77 | } | ||
78 | msleep(1); | ||
79 | } | ||
80 | |||
81 | /* wait for transfer to complete */ | ||
82 | timeout = jiffies + usecs_to_jiffies(us2); | ||
83 | while (1) { | ||
84 | err = time_after(jiffies, timeout); | ||
85 | if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) | ||
86 | break; | ||
87 | saa7146_read(dev, MC2); | ||
88 | if (err) { | ||
89 | DEB_S("%s: %s timed out while waiting for transfer completion\n", | ||
90 | dev->name, __func__); | ||
91 | return -ETIMEDOUT; | ||
92 | } | ||
93 | msleep(1); | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev, | ||
100 | unsigned long us1, unsigned long us2) | ||
101 | { | ||
102 | unsigned long loops; | ||
103 | |||
104 | /* wait for registers to be programmed */ | ||
105 | loops = us1; | ||
106 | while (1) { | ||
107 | if (saa7146_read(dev, MC2) & 2) | ||
108 | break; | ||
109 | if (!loops--) { | ||
110 | pr_err("%s: %s timed out while waiting for registers getting programmed\n", | ||
111 | dev->name, __func__); | ||
112 | return -ETIMEDOUT; | ||
113 | } | ||
114 | udelay(1); | ||
115 | } | ||
116 | |||
117 | /* wait for transfer to complete */ | ||
118 | loops = us2 / 5; | ||
119 | while (1) { | ||
120 | if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) | ||
121 | break; | ||
122 | saa7146_read(dev, MC2); | ||
123 | if (!loops--) { | ||
124 | DEB_S("%s: %s timed out while waiting for transfer completion\n", | ||
125 | dev->name, __func__); | ||
126 | return -ETIMEDOUT; | ||
127 | } | ||
128 | udelay(5); | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) | ||
135 | { | ||
136 | if (nobusyloop) | ||
137 | return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000); | ||
138 | else | ||
139 | return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000); | ||
140 | } | ||
141 | |||
142 | /**************************************************************************** | ||
143 | * general helper functions | ||
144 | ****************************************************************************/ | ||
145 | |||
146 | /* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c | ||
147 | make sure virt has been allocated with vmalloc_32(), otherwise the BUG() | ||
148 | may be triggered on highmem machines */ | ||
149 | static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) | ||
150 | { | ||
151 | struct scatterlist *sglist; | ||
152 | struct page *pg; | ||
153 | int i; | ||
154 | |||
155 | sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); | ||
156 | if (NULL == sglist) | ||
157 | return NULL; | ||
158 | sg_init_table(sglist, nr_pages); | ||
159 | for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { | ||
160 | pg = vmalloc_to_page(virt); | ||
161 | if (NULL == pg) | ||
162 | goto err; | ||
163 | BUG_ON(PageHighMem(pg)); | ||
164 | sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); | ||
165 | } | ||
166 | return sglist; | ||
167 | |||
168 | err: | ||
169 | kfree(sglist); | ||
170 | return NULL; | ||
171 | } | ||
172 | |||
173 | /********************************************************************************/ | ||
174 | /* common page table functions */ | ||
175 | |||
176 | void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt) | ||
177 | { | ||
178 | int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; | ||
179 | void *mem = vmalloc_32(length); | ||
180 | int slen = 0; | ||
181 | |||
182 | if (NULL == mem) | ||
183 | goto err_null; | ||
184 | |||
185 | if (!(pt->slist = vmalloc_to_sg(mem, pages))) | ||
186 | goto err_free_mem; | ||
187 | |||
188 | if (saa7146_pgtable_alloc(pci, pt)) | ||
189 | goto err_free_slist; | ||
190 | |||
191 | pt->nents = pages; | ||
192 | slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE); | ||
193 | if (0 == slen) | ||
194 | goto err_free_pgtable; | ||
195 | |||
196 | if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) | ||
197 | goto err_unmap_sg; | ||
198 | |||
199 | return mem; | ||
200 | |||
201 | err_unmap_sg: | ||
202 | pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); | ||
203 | err_free_pgtable: | ||
204 | saa7146_pgtable_free(pci, pt); | ||
205 | err_free_slist: | ||
206 | kfree(pt->slist); | ||
207 | pt->slist = NULL; | ||
208 | err_free_mem: | ||
209 | vfree(mem); | ||
210 | err_null: | ||
211 | return NULL; | ||
212 | } | ||
213 | |||
214 | void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, void *mem, struct saa7146_pgtable *pt) | ||
215 | { | ||
216 | pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); | ||
217 | saa7146_pgtable_free(pci, pt); | ||
218 | kfree(pt->slist); | ||
219 | pt->slist = NULL; | ||
220 | vfree(mem); | ||
221 | } | ||
222 | |||
223 | void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) | ||
224 | { | ||
225 | if (NULL == pt->cpu) | ||
226 | return; | ||
227 | pci_free_consistent(pci, pt->size, pt->cpu, pt->dma); | ||
228 | pt->cpu = NULL; | ||
229 | } | ||
230 | |||
231 | int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) | ||
232 | { | ||
233 | __le32 *cpu; | ||
234 | dma_addr_t dma_addr = 0; | ||
235 | |||
236 | cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); | ||
237 | if (NULL == cpu) { | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | pt->size = PAGE_SIZE; | ||
241 | pt->cpu = cpu; | ||
242 | pt->dma = dma_addr; | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, | ||
248 | struct scatterlist *list, int sglen ) | ||
249 | { | ||
250 | __le32 *ptr, fill; | ||
251 | int nr_pages = 0; | ||
252 | int i,p; | ||
253 | |||
254 | BUG_ON(0 == sglen); | ||
255 | BUG_ON(list->offset > PAGE_SIZE); | ||
256 | |||
257 | /* if we have a user buffer, the first page may not be | ||
258 | aligned to a page boundary. */ | ||
259 | pt->offset = list->offset; | ||
260 | |||
261 | ptr = pt->cpu; | ||
262 | for (i = 0; i < sglen; i++, list++) { | ||
263 | /* | ||
264 | pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n", | ||
265 | i, sg_dma_address(list), sg_dma_len(list), | ||
266 | list->offset); | ||
267 | */ | ||
268 | for (p = 0; p * 4096 < list->length; p++, ptr++) { | ||
269 | *ptr = cpu_to_le32(sg_dma_address(list) + p * 4096); | ||
270 | nr_pages++; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | |||
275 | /* safety; fill the page table up with the last valid page */ | ||
276 | fill = *(ptr-1); | ||
277 | for(i=nr_pages;i<1024;i++) { | ||
278 | *ptr++ = fill; | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | ptr = pt->cpu; | ||
283 | pr_debug("offset: %d\n", pt->offset); | ||
284 | for(i=0;i<5;i++) { | ||
285 | pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]); | ||
286 | } | ||
287 | */ | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /********************************************************************************/ | ||
292 | /* interrupt handler */ | ||
293 | static irqreturn_t interrupt_hw(int irq, void *dev_id) | ||
294 | { | ||
295 | struct saa7146_dev *dev = dev_id; | ||
296 | u32 isr; | ||
297 | u32 ack_isr; | ||
298 | |||
299 | /* read out the interrupt status register */ | ||
300 | ack_isr = isr = saa7146_read(dev, ISR); | ||
301 | |||
302 | /* is this our interrupt? */ | ||
303 | if ( 0 == isr ) { | ||
304 | /* nope, some other device */ | ||
305 | return IRQ_NONE; | ||
306 | } | ||
307 | |||
308 | if (dev->ext) { | ||
309 | if (dev->ext->irq_mask & isr) { | ||
310 | if (dev->ext->irq_func) | ||
311 | dev->ext->irq_func(dev, &isr); | ||
312 | isr &= ~dev->ext->irq_mask; | ||
313 | } | ||
314 | } | ||
315 | if (0 != (isr & (MASK_27))) { | ||
316 | DEB_INT("irq: RPS0 (0x%08x)\n", isr); | ||
317 | if (dev->vv_data && dev->vv_callback) | ||
318 | dev->vv_callback(dev,isr); | ||
319 | isr &= ~MASK_27; | ||
320 | } | ||
321 | if (0 != (isr & (MASK_28))) { | ||
322 | if (dev->vv_data && dev->vv_callback) | ||
323 | dev->vv_callback(dev,isr); | ||
324 | isr &= ~MASK_28; | ||
325 | } | ||
326 | if (0 != (isr & (MASK_16|MASK_17))) { | ||
327 | SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); | ||
328 | /* only wake up if we expect something */ | ||
329 | if (0 != dev->i2c_op) { | ||
330 | dev->i2c_op = 0; | ||
331 | wake_up(&dev->i2c_wq); | ||
332 | } else { | ||
333 | u32 psr = saa7146_read(dev, PSR); | ||
334 | u32 ssr = saa7146_read(dev, SSR); | ||
335 | pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n", | ||
336 | dev->name, isr, psr, ssr); | ||
337 | } | ||
338 | isr &= ~(MASK_16|MASK_17); | ||
339 | } | ||
340 | if( 0 != isr ) { | ||
341 | ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n", | ||
342 | isr); | ||
343 | ERR("disabling interrupt source(s)!\n"); | ||
344 | SAA7146_IER_DISABLE(dev,isr); | ||
345 | } | ||
346 | saa7146_write(dev, ISR, ack_isr); | ||
347 | return IRQ_HANDLED; | ||
348 | } | ||
349 | |||
350 | /*********************************************************************************/ | ||
351 | /* configuration-functions */ | ||
352 | |||
353 | static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) | ||
354 | { | ||
355 | struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data; | ||
356 | struct saa7146_extension *ext = pci_ext->ext; | ||
357 | struct saa7146_dev *dev; | ||
358 | int err = -ENOMEM; | ||
359 | |||
360 | /* clear out mem for sure */ | ||
361 | dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL); | ||
362 | if (!dev) { | ||
363 | ERR("out of memory\n"); | ||
364 | goto out; | ||
365 | } | ||
366 | |||
367 | DEB_EE("pci:%p\n", pci); | ||
368 | |||
369 | err = pci_enable_device(pci); | ||
370 | if (err < 0) { | ||
371 | ERR("pci_enable_device() failed\n"); | ||
372 | goto err_free; | ||
373 | } | ||
374 | |||
375 | /* enable bus-mastering */ | ||
376 | pci_set_master(pci); | ||
377 | |||
378 | dev->pci = pci; | ||
379 | |||
380 | /* get chip-revision; this is needed to enable bug-fixes */ | ||
381 | dev->revision = pci->revision; | ||
382 | |||
383 | /* remap the memory from virtual to physical address */ | ||
384 | |||
385 | err = pci_request_region(pci, 0, "saa7146"); | ||
386 | if (err < 0) | ||
387 | goto err_disable; | ||
388 | |||
389 | dev->mem = ioremap(pci_resource_start(pci, 0), | ||
390 | pci_resource_len(pci, 0)); | ||
391 | if (!dev->mem) { | ||
392 | ERR("ioremap() failed\n"); | ||
393 | err = -ENODEV; | ||
394 | goto err_release; | ||
395 | } | ||
396 | |||
397 | /* we don't do a master reset here anymore, it screws up | ||
398 | some boards that don't have an i2c-eeprom for configuration | ||
399 | values */ | ||
400 | /* | ||
401 | saa7146_write(dev, MC1, MASK_31); | ||
402 | */ | ||
403 | |||
404 | /* disable all irqs */ | ||
405 | saa7146_write(dev, IER, 0); | ||
406 | |||
407 | /* shut down all dma transfers and rps tasks */ | ||
408 | saa7146_write(dev, MC1, 0x30ff0000); | ||
409 | |||
410 | /* clear out any rps-signals pending */ | ||
411 | saa7146_write(dev, MC2, 0xf8000000); | ||
412 | |||
413 | /* request an interrupt for the saa7146 */ | ||
414 | err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED, | ||
415 | dev->name, dev); | ||
416 | if (err < 0) { | ||
417 | ERR("request_irq() failed\n"); | ||
418 | goto err_unmap; | ||
419 | } | ||
420 | |||
421 | err = -ENOMEM; | ||
422 | |||
423 | /* get memory for various stuff */ | ||
424 | dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, | ||
425 | &dev->d_rps0.dma_handle); | ||
426 | if (!dev->d_rps0.cpu_addr) | ||
427 | goto err_free_irq; | ||
428 | memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM); | ||
429 | |||
430 | dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, | ||
431 | &dev->d_rps1.dma_handle); | ||
432 | if (!dev->d_rps1.cpu_addr) | ||
433 | goto err_free_rps0; | ||
434 | memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM); | ||
435 | |||
436 | dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM, | ||
437 | &dev->d_i2c.dma_handle); | ||
438 | if (!dev->d_i2c.cpu_addr) | ||
439 | goto err_free_rps1; | ||
440 | memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM); | ||
441 | |||
442 | /* the rest + print status message */ | ||
443 | |||
444 | /* create a nice device name */ | ||
445 | sprintf(dev->name, "saa7146 (%d)", saa7146_num); | ||
446 | |||
447 | pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n", | ||
448 | dev->mem, dev->revision, pci->irq, | ||
449 | pci->subsystem_vendor, pci->subsystem_device); | ||
450 | dev->ext = ext; | ||
451 | |||
452 | mutex_init(&dev->v4l2_lock); | ||
453 | spin_lock_init(&dev->int_slock); | ||
454 | spin_lock_init(&dev->slock); | ||
455 | |||
456 | mutex_init(&dev->i2c_lock); | ||
457 | |||
458 | dev->module = THIS_MODULE; | ||
459 | init_waitqueue_head(&dev->i2c_wq); | ||
460 | |||
461 | /* set some sane pci arbitrition values */ | ||
462 | saa7146_write(dev, PCI_BT_V1, 0x1c00101f); | ||
463 | |||
464 | /* TODO: use the status code of the callback */ | ||
465 | |||
466 | err = -ENODEV; | ||
467 | |||
468 | if (ext->probe && ext->probe(dev)) { | ||
469 | DEB_D("ext->probe() failed for %p. skipping device.\n", dev); | ||
470 | goto err_free_i2c; | ||
471 | } | ||
472 | |||
473 | if (ext->attach(dev, pci_ext)) { | ||
474 | DEB_D("ext->attach() failed for %p. skipping device.\n", dev); | ||
475 | goto err_free_i2c; | ||
476 | } | ||
477 | /* V4L extensions will set the pci drvdata to the v4l2_device in the | ||
478 | attach() above. So for those cards that do not use V4L we have to | ||
479 | set it explicitly. */ | ||
480 | pci_set_drvdata(pci, &dev->v4l2_dev); | ||
481 | |||
482 | saa7146_num++; | ||
483 | |||
484 | err = 0; | ||
485 | out: | ||
486 | return err; | ||
487 | |||
488 | err_free_i2c: | ||
489 | pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, | ||
490 | dev->d_i2c.dma_handle); | ||
491 | err_free_rps1: | ||
492 | pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, | ||
493 | dev->d_rps1.dma_handle); | ||
494 | err_free_rps0: | ||
495 | pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, | ||
496 | dev->d_rps0.dma_handle); | ||
497 | err_free_irq: | ||
498 | free_irq(pci->irq, (void *)dev); | ||
499 | err_unmap: | ||
500 | iounmap(dev->mem); | ||
501 | err_release: | ||
502 | pci_release_region(pci, 0); | ||
503 | err_disable: | ||
504 | pci_disable_device(pci); | ||
505 | err_free: | ||
506 | kfree(dev); | ||
507 | goto out; | ||
508 | } | ||
509 | |||
510 | static void saa7146_remove_one(struct pci_dev *pdev) | ||
511 | { | ||
512 | struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); | ||
513 | struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev); | ||
514 | struct { | ||
515 | void *addr; | ||
516 | dma_addr_t dma; | ||
517 | } dev_map[] = { | ||
518 | { dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle }, | ||
519 | { dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle }, | ||
520 | { dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle }, | ||
521 | { NULL, 0 } | ||
522 | }, *p; | ||
523 | |||
524 | DEB_EE("dev:%p\n", dev); | ||
525 | |||
526 | dev->ext->detach(dev); | ||
527 | /* Zero the PCI drvdata after use. */ | ||
528 | pci_set_drvdata(pdev, NULL); | ||
529 | |||
530 | /* shut down all video dma transfers */ | ||
531 | saa7146_write(dev, MC1, 0x00ff0000); | ||
532 | |||
533 | /* disable all irqs, release irq-routine */ | ||
534 | saa7146_write(dev, IER, 0); | ||
535 | |||
536 | free_irq(pdev->irq, dev); | ||
537 | |||
538 | for (p = dev_map; p->addr; p++) | ||
539 | pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma); | ||
540 | |||
541 | iounmap(dev->mem); | ||
542 | pci_release_region(pdev, 0); | ||
543 | pci_disable_device(pdev); | ||
544 | kfree(dev); | ||
545 | |||
546 | saa7146_num--; | ||
547 | } | ||
548 | |||
549 | /*********************************************************************************/ | ||
550 | /* extension handling functions */ | ||
551 | |||
552 | int saa7146_register_extension(struct saa7146_extension* ext) | ||
553 | { | ||
554 | DEB_EE("ext:%p\n", ext); | ||
555 | |||
556 | ext->driver.name = ext->name; | ||
557 | ext->driver.id_table = ext->pci_tbl; | ||
558 | ext->driver.probe = saa7146_init_one; | ||
559 | ext->driver.remove = saa7146_remove_one; | ||
560 | |||
561 | pr_info("register extension '%s'\n", ext->name); | ||
562 | return pci_register_driver(&ext->driver); | ||
563 | } | ||
564 | |||
565 | int saa7146_unregister_extension(struct saa7146_extension* ext) | ||
566 | { | ||
567 | DEB_EE("ext:%p\n", ext); | ||
568 | pr_info("unregister extension '%s'\n", ext->name); | ||
569 | pci_unregister_driver(&ext->driver); | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | EXPORT_SYMBOL_GPL(saa7146_register_extension); | ||
574 | EXPORT_SYMBOL_GPL(saa7146_unregister_extension); | ||
575 | |||
576 | /* misc functions used by extension modules */ | ||
577 | EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); | ||
578 | EXPORT_SYMBOL_GPL(saa7146_pgtable_free); | ||
579 | EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); | ||
580 | EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); | ||
581 | EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable); | ||
582 | EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); | ||
583 | |||
584 | EXPORT_SYMBOL_GPL(saa7146_setgpio); | ||
585 | |||
586 | EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); | ||
587 | |||
588 | EXPORT_SYMBOL_GPL(saa7146_debug); | ||
589 | |||
590 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
591 | MODULE_DESCRIPTION("driver for generic saa7146-based hardware"); | ||
592 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c deleted file mode 100644 index b3890bd49df..00000000000 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ /dev/null | |||
@@ -1,664 +0,0 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
3 | #include <media/saa7146_vv.h> | ||
4 | #include <linux/module.h> | ||
5 | |||
6 | /****************************************************************************/ | ||
7 | /* resource management functions, shamelessly stolen from saa7134 driver */ | ||
8 | |||
9 | int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) | ||
10 | { | ||
11 | struct saa7146_dev *dev = fh->dev; | ||
12 | struct saa7146_vv *vv = dev->vv_data; | ||
13 | |||
14 | if (fh->resources & bit) { | ||
15 | DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n", | ||
16 | bit, vv->resources); | ||
17 | /* have it already allocated */ | ||
18 | return 1; | ||
19 | } | ||
20 | |||
21 | /* is it free? */ | ||
22 | if (vv->resources & bit) { | ||
23 | DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n", | ||
24 | vv->resources, bit); | ||
25 | /* no, someone else uses it */ | ||
26 | return 0; | ||
27 | } | ||
28 | /* it's free, grab it */ | ||
29 | fh->resources |= bit; | ||
30 | vv->resources |= bit; | ||
31 | DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources); | ||
32 | return 1; | ||
33 | } | ||
34 | |||
35 | void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) | ||
36 | { | ||
37 | struct saa7146_dev *dev = fh->dev; | ||
38 | struct saa7146_vv *vv = dev->vv_data; | ||
39 | |||
40 | BUG_ON((fh->resources & bits) != bits); | ||
41 | |||
42 | fh->resources &= ~bits; | ||
43 | vv->resources &= ~bits; | ||
44 | DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources); | ||
45 | } | ||
46 | |||
47 | |||
48 | /********************************************************************************/ | ||
49 | /* common dma functions */ | ||
50 | |||
51 | void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, | ||
52 | struct saa7146_buf *buf) | ||
53 | { | ||
54 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
55 | DEB_EE("dev:%p, buf:%p\n", dev, buf); | ||
56 | |||
57 | BUG_ON(in_interrupt()); | ||
58 | |||
59 | videobuf_waiton(q, &buf->vb, 0, 0); | ||
60 | videobuf_dma_unmap(q->dev, dma); | ||
61 | videobuf_dma_free(dma); | ||
62 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
63 | } | ||
64 | |||
65 | |||
66 | /********************************************************************************/ | ||
67 | /* common buffer functions */ | ||
68 | |||
69 | int saa7146_buffer_queue(struct saa7146_dev *dev, | ||
70 | struct saa7146_dmaqueue *q, | ||
71 | struct saa7146_buf *buf) | ||
72 | { | ||
73 | assert_spin_locked(&dev->slock); | ||
74 | DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf); | ||
75 | |||
76 | BUG_ON(!q); | ||
77 | |||
78 | if (NULL == q->curr) { | ||
79 | q->curr = buf; | ||
80 | DEB_D("immediately activating buffer %p\n", buf); | ||
81 | buf->activate(dev,buf,NULL); | ||
82 | } else { | ||
83 | list_add_tail(&buf->vb.queue,&q->queue); | ||
84 | buf->vb.state = VIDEOBUF_QUEUED; | ||
85 | DEB_D("adding buffer %p to queue. (active buffer present)\n", | ||
86 | buf); | ||
87 | } | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | void saa7146_buffer_finish(struct saa7146_dev *dev, | ||
92 | struct saa7146_dmaqueue *q, | ||
93 | int state) | ||
94 | { | ||
95 | assert_spin_locked(&dev->slock); | ||
96 | DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state); | ||
97 | DEB_EE("q->curr:%p\n", q->curr); | ||
98 | |||
99 | BUG_ON(!q->curr); | ||
100 | |||
101 | /* finish current buffer */ | ||
102 | if (NULL == q->curr) { | ||
103 | DEB_D("aiii. no current buffer\n"); | ||
104 | return; | ||
105 | } | ||
106 | |||
107 | q->curr->vb.state = state; | ||
108 | do_gettimeofday(&q->curr->vb.ts); | ||
109 | wake_up(&q->curr->vb.done); | ||
110 | |||
111 | q->curr = NULL; | ||
112 | } | ||
113 | |||
114 | void saa7146_buffer_next(struct saa7146_dev *dev, | ||
115 | struct saa7146_dmaqueue *q, int vbi) | ||
116 | { | ||
117 | struct saa7146_buf *buf,*next = NULL; | ||
118 | |||
119 | BUG_ON(!q); | ||
120 | |||
121 | DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi); | ||
122 | |||
123 | assert_spin_locked(&dev->slock); | ||
124 | if (!list_empty(&q->queue)) { | ||
125 | /* activate next one from queue */ | ||
126 | buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue); | ||
127 | list_del(&buf->vb.queue); | ||
128 | if (!list_empty(&q->queue)) | ||
129 | next = list_entry(q->queue.next,struct saa7146_buf, vb.queue); | ||
130 | q->curr = buf; | ||
131 | DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n", | ||
132 | buf, q->queue.prev, q->queue.next); | ||
133 | buf->activate(dev,buf,next); | ||
134 | } else { | ||
135 | DEB_INT("no next buffer. stopping.\n"); | ||
136 | if( 0 != vbi ) { | ||
137 | /* turn off video-dma3 */ | ||
138 | saa7146_write(dev,MC1, MASK_20); | ||
139 | } else { | ||
140 | /* nothing to do -- just prevent next video-dma1 transfer | ||
141 | by lowering the protection address */ | ||
142 | |||
143 | // fixme: fix this for vflip != 0 | ||
144 | |||
145 | saa7146_write(dev, PROT_ADDR1, 0); | ||
146 | saa7146_write(dev, MC2, (MASK_02|MASK_18)); | ||
147 | |||
148 | /* write the address of the rps-program */ | ||
149 | saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle); | ||
150 | /* turn on rps */ | ||
151 | saa7146_write(dev, MC1, (MASK_12 | MASK_28)); | ||
152 | |||
153 | /* | ||
154 | printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1)); | ||
155 | printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1)); | ||
156 | printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1)); | ||
157 | printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1)); | ||
158 | printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1)); | ||
159 | printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1)); | ||
160 | */ | ||
161 | } | ||
162 | del_timer(&q->timeout); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | void saa7146_buffer_timeout(unsigned long data) | ||
167 | { | ||
168 | struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data; | ||
169 | struct saa7146_dev *dev = q->dev; | ||
170 | unsigned long flags; | ||
171 | |||
172 | DEB_EE("dev:%p, dmaq:%p\n", dev, q); | ||
173 | |||
174 | spin_lock_irqsave(&dev->slock,flags); | ||
175 | if (q->curr) { | ||
176 | DEB_D("timeout on %p\n", q->curr); | ||
177 | saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR); | ||
178 | } | ||
179 | |||
180 | /* we don't restart the transfer here like other drivers do. when | ||
181 | a streaming capture is disabled, the timeout function will be | ||
182 | called for the current buffer. if we activate the next buffer now, | ||
183 | we mess up our capture logic. if a timeout occurs on another buffer, | ||
184 | then something is seriously broken before, so no need to buffer the | ||
185 | next capture IMHO... */ | ||
186 | /* | ||
187 | saa7146_buffer_next(dev,q); | ||
188 | */ | ||
189 | spin_unlock_irqrestore(&dev->slock,flags); | ||
190 | } | ||
191 | |||
192 | /********************************************************************************/ | ||
193 | /* file operations */ | ||
194 | |||
195 | static int fops_open(struct file *file) | ||
196 | { | ||
197 | struct video_device *vdev = video_devdata(file); | ||
198 | struct saa7146_dev *dev = video_drvdata(file); | ||
199 | struct saa7146_fh *fh = NULL; | ||
200 | int result = 0; | ||
201 | |||
202 | DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev)); | ||
203 | |||
204 | if (mutex_lock_interruptible(vdev->lock)) | ||
205 | return -ERESTARTSYS; | ||
206 | |||
207 | DEB_D("using: %p\n", dev); | ||
208 | |||
209 | /* check if an extension is registered */ | ||
210 | if( NULL == dev->ext ) { | ||
211 | DEB_S("no extension registered for this device\n"); | ||
212 | result = -ENODEV; | ||
213 | goto out; | ||
214 | } | ||
215 | |||
216 | /* allocate per open data */ | ||
217 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | ||
218 | if (NULL == fh) { | ||
219 | DEB_S("cannot allocate memory for per open data\n"); | ||
220 | result = -ENOMEM; | ||
221 | goto out; | ||
222 | } | ||
223 | |||
224 | v4l2_fh_init(&fh->fh, vdev); | ||
225 | |||
226 | file->private_data = &fh->fh; | ||
227 | fh->dev = dev; | ||
228 | |||
229 | if (vdev->vfl_type == VFL_TYPE_VBI) { | ||
230 | DEB_S("initializing vbi...\n"); | ||
231 | if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) | ||
232 | result = saa7146_vbi_uops.open(dev,file); | ||
233 | if (dev->ext_vv_data->vbi_fops.open) | ||
234 | dev->ext_vv_data->vbi_fops.open(file); | ||
235 | } else { | ||
236 | DEB_S("initializing video...\n"); | ||
237 | result = saa7146_video_uops.open(dev,file); | ||
238 | } | ||
239 | |||
240 | if (0 != result) { | ||
241 | goto out; | ||
242 | } | ||
243 | |||
244 | if( 0 == try_module_get(dev->ext->module)) { | ||
245 | result = -EINVAL; | ||
246 | goto out; | ||
247 | } | ||
248 | |||
249 | result = 0; | ||
250 | v4l2_fh_add(&fh->fh); | ||
251 | out: | ||
252 | if (fh && result != 0) { | ||
253 | kfree(fh); | ||
254 | file->private_data = NULL; | ||
255 | } | ||
256 | mutex_unlock(vdev->lock); | ||
257 | return result; | ||
258 | } | ||
259 | |||
260 | static int fops_release(struct file *file) | ||
261 | { | ||
262 | struct video_device *vdev = video_devdata(file); | ||
263 | struct saa7146_fh *fh = file->private_data; | ||
264 | struct saa7146_dev *dev = fh->dev; | ||
265 | |||
266 | DEB_EE("file:%p\n", file); | ||
267 | |||
268 | if (mutex_lock_interruptible(vdev->lock)) | ||
269 | return -ERESTARTSYS; | ||
270 | |||
271 | if (vdev->vfl_type == VFL_TYPE_VBI) { | ||
272 | if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) | ||
273 | saa7146_vbi_uops.release(dev,file); | ||
274 | if (dev->ext_vv_data->vbi_fops.release) | ||
275 | dev->ext_vv_data->vbi_fops.release(file); | ||
276 | } else { | ||
277 | saa7146_video_uops.release(dev,file); | ||
278 | } | ||
279 | |||
280 | v4l2_fh_del(&fh->fh); | ||
281 | v4l2_fh_exit(&fh->fh); | ||
282 | module_put(dev->ext->module); | ||
283 | file->private_data = NULL; | ||
284 | kfree(fh); | ||
285 | |||
286 | mutex_unlock(vdev->lock); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int fops_mmap(struct file *file, struct vm_area_struct * vma) | ||
292 | { | ||
293 | struct video_device *vdev = video_devdata(file); | ||
294 | struct saa7146_fh *fh = file->private_data; | ||
295 | struct videobuf_queue *q; | ||
296 | int res; | ||
297 | |||
298 | switch (vdev->vfl_type) { | ||
299 | case VFL_TYPE_GRABBER: { | ||
300 | DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n", | ||
301 | file, vma); | ||
302 | q = &fh->video_q; | ||
303 | break; | ||
304 | } | ||
305 | case VFL_TYPE_VBI: { | ||
306 | DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n", | ||
307 | file, vma); | ||
308 | if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT) | ||
309 | return -ENODEV; | ||
310 | q = &fh->vbi_q; | ||
311 | break; | ||
312 | } | ||
313 | default: | ||
314 | BUG(); | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | if (mutex_lock_interruptible(vdev->lock)) | ||
319 | return -ERESTARTSYS; | ||
320 | res = videobuf_mmap_mapper(q, vma); | ||
321 | mutex_unlock(vdev->lock); | ||
322 | return res; | ||
323 | } | ||
324 | |||
325 | static unsigned int __fops_poll(struct file *file, struct poll_table_struct *wait) | ||
326 | { | ||
327 | struct video_device *vdev = video_devdata(file); | ||
328 | struct saa7146_fh *fh = file->private_data; | ||
329 | struct videobuf_buffer *buf = NULL; | ||
330 | struct videobuf_queue *q; | ||
331 | unsigned int res = v4l2_ctrl_poll(file, wait); | ||
332 | |||
333 | DEB_EE("file:%p, poll:%p\n", file, wait); | ||
334 | |||
335 | if (vdev->vfl_type == VFL_TYPE_VBI) { | ||
336 | if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT) | ||
337 | return res | POLLOUT | POLLWRNORM; | ||
338 | if( 0 == fh->vbi_q.streaming ) | ||
339 | return res | videobuf_poll_stream(file, &fh->vbi_q, wait); | ||
340 | q = &fh->vbi_q; | ||
341 | } else { | ||
342 | DEB_D("using video queue\n"); | ||
343 | q = &fh->video_q; | ||
344 | } | ||
345 | |||
346 | if (!list_empty(&q->stream)) | ||
347 | buf = list_entry(q->stream.next, struct videobuf_buffer, stream); | ||
348 | |||
349 | if (!buf) { | ||
350 | DEB_D("buf == NULL!\n"); | ||
351 | return res | POLLERR; | ||
352 | } | ||
353 | |||
354 | poll_wait(file, &buf->done, wait); | ||
355 | if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) { | ||
356 | DEB_D("poll succeeded!\n"); | ||
357 | return res | POLLIN | POLLRDNORM; | ||
358 | } | ||
359 | |||
360 | DEB_D("nothing to poll for, buf->state:%d\n", buf->state); | ||
361 | return res; | ||
362 | } | ||
363 | |||
364 | static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) | ||
365 | { | ||
366 | struct video_device *vdev = video_devdata(file); | ||
367 | unsigned int res; | ||
368 | |||
369 | mutex_lock(vdev->lock); | ||
370 | res = __fops_poll(file, wait); | ||
371 | mutex_unlock(vdev->lock); | ||
372 | return res; | ||
373 | } | ||
374 | |||
375 | static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
376 | { | ||
377 | struct video_device *vdev = video_devdata(file); | ||
378 | struct saa7146_fh *fh = file->private_data; | ||
379 | int ret; | ||
380 | |||
381 | switch (vdev->vfl_type) { | ||
382 | case VFL_TYPE_GRABBER: | ||
383 | /* | ||
384 | DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", | ||
385 | file, data, (unsigned long)count); | ||
386 | */ | ||
387 | return saa7146_video_uops.read(file,data,count,ppos); | ||
388 | case VFL_TYPE_VBI: | ||
389 | /* | ||
390 | DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", | ||
391 | file, data, (unsigned long)count); | ||
392 | */ | ||
393 | if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) { | ||
394 | if (mutex_lock_interruptible(vdev->lock)) | ||
395 | return -ERESTARTSYS; | ||
396 | ret = saa7146_vbi_uops.read(file, data, count, ppos); | ||
397 | mutex_unlock(vdev->lock); | ||
398 | return ret; | ||
399 | } | ||
400 | return -EINVAL; | ||
401 | default: | ||
402 | BUG(); | ||
403 | return 0; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) | ||
408 | { | ||
409 | struct video_device *vdev = video_devdata(file); | ||
410 | struct saa7146_fh *fh = file->private_data; | ||
411 | int ret; | ||
412 | |||
413 | switch (vdev->vfl_type) { | ||
414 | case VFL_TYPE_GRABBER: | ||
415 | return -EINVAL; | ||
416 | case VFL_TYPE_VBI: | ||
417 | if (fh->dev->ext_vv_data->vbi_fops.write) { | ||
418 | if (mutex_lock_interruptible(vdev->lock)) | ||
419 | return -ERESTARTSYS; | ||
420 | ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos); | ||
421 | mutex_unlock(vdev->lock); | ||
422 | return ret; | ||
423 | } | ||
424 | return -EINVAL; | ||
425 | default: | ||
426 | BUG(); | ||
427 | return -EINVAL; | ||
428 | } | ||
429 | } | ||
430 | |||
431 | static const struct v4l2_file_operations video_fops = | ||
432 | { | ||
433 | .owner = THIS_MODULE, | ||
434 | .open = fops_open, | ||
435 | .release = fops_release, | ||
436 | .read = fops_read, | ||
437 | .write = fops_write, | ||
438 | .poll = fops_poll, | ||
439 | .mmap = fops_mmap, | ||
440 | .unlocked_ioctl = video_ioctl2, | ||
441 | }; | ||
442 | |||
443 | static void vv_callback(struct saa7146_dev *dev, unsigned long status) | ||
444 | { | ||
445 | u32 isr = status; | ||
446 | |||
447 | DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status); | ||
448 | |||
449 | if (0 != (isr & (MASK_27))) { | ||
450 | DEB_INT("irq: RPS0 (0x%08x)\n", isr); | ||
451 | saa7146_video_uops.irq_done(dev,isr); | ||
452 | } | ||
453 | |||
454 | if (0 != (isr & (MASK_28))) { | ||
455 | u32 mc2 = saa7146_read(dev, MC2); | ||
456 | if( 0 != (mc2 & MASK_15)) { | ||
457 | DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr); | ||
458 | wake_up(&dev->vv_data->vbi_wq); | ||
459 | saa7146_write(dev,MC2, MASK_31); | ||
460 | return; | ||
461 | } | ||
462 | DEB_INT("irq: RPS1 (0x%08x)\n", isr); | ||
463 | saa7146_vbi_uops.irq_done(dev,isr); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static const struct v4l2_ctrl_ops saa7146_ctrl_ops = { | ||
468 | .s_ctrl = saa7146_s_ctrl, | ||
469 | }; | ||
470 | |||
471 | int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) | ||
472 | { | ||
473 | struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; | ||
474 | struct v4l2_pix_format *fmt; | ||
475 | struct v4l2_vbi_format *vbi; | ||
476 | struct saa7146_vv *vv; | ||
477 | int err; | ||
478 | |||
479 | err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); | ||
480 | if (err) | ||
481 | return err; | ||
482 | |||
483 | v4l2_ctrl_handler_init(hdl, 6); | ||
484 | v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, | ||
485 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); | ||
486 | v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, | ||
487 | V4L2_CID_CONTRAST, 0, 127, 1, 64); | ||
488 | v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, | ||
489 | V4L2_CID_SATURATION, 0, 127, 1, 64); | ||
490 | v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, | ||
491 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
492 | v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops, | ||
493 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
494 | if (hdl->error) { | ||
495 | err = hdl->error; | ||
496 | v4l2_ctrl_handler_free(hdl); | ||
497 | return err; | ||
498 | } | ||
499 | dev->v4l2_dev.ctrl_handler = hdl; | ||
500 | |||
501 | vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); | ||
502 | if (vv == NULL) { | ||
503 | ERR("out of memory. aborting.\n"); | ||
504 | v4l2_ctrl_handler_free(hdl); | ||
505 | return -ENOMEM; | ||
506 | } | ||
507 | ext_vv->vid_ops = saa7146_video_ioctl_ops; | ||
508 | ext_vv->vbi_ops = saa7146_vbi_ioctl_ops; | ||
509 | ext_vv->core_ops = &saa7146_video_ioctl_ops; | ||
510 | |||
511 | DEB_EE("dev:%p\n", dev); | ||
512 | |||
513 | /* set default values for video parts of the saa7146 */ | ||
514 | saa7146_write(dev, BCS_CTRL, 0x80400040); | ||
515 | |||
516 | /* enable video-port pins */ | ||
517 | saa7146_write(dev, MC1, (MASK_10 | MASK_26)); | ||
518 | |||
519 | /* save per-device extension data (one extension can | ||
520 | handle different devices that might need different | ||
521 | configuration data) */ | ||
522 | dev->ext_vv_data = ext_vv; | ||
523 | |||
524 | vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle); | ||
525 | if( NULL == vv->d_clipping.cpu_addr ) { | ||
526 | ERR("out of memory. aborting.\n"); | ||
527 | kfree(vv); | ||
528 | v4l2_ctrl_handler_free(hdl); | ||
529 | return -1; | ||
530 | } | ||
531 | memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); | ||
532 | |||
533 | saa7146_video_uops.init(dev,vv); | ||
534 | if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) | ||
535 | saa7146_vbi_uops.init(dev,vv); | ||
536 | |||
537 | fmt = &vv->ov_fb.fmt; | ||
538 | fmt->width = vv->standard->h_max_out; | ||
539 | fmt->height = vv->standard->v_max_out; | ||
540 | fmt->pixelformat = V4L2_PIX_FMT_RGB565; | ||
541 | fmt->bytesperline = 2 * fmt->width; | ||
542 | fmt->sizeimage = fmt->bytesperline * fmt->height; | ||
543 | fmt->colorspace = V4L2_COLORSPACE_SRGB; | ||
544 | |||
545 | fmt = &vv->video_fmt; | ||
546 | fmt->width = 384; | ||
547 | fmt->height = 288; | ||
548 | fmt->pixelformat = V4L2_PIX_FMT_BGR24; | ||
549 | fmt->field = V4L2_FIELD_ANY; | ||
550 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
551 | fmt->bytesperline = 3 * fmt->width; | ||
552 | fmt->sizeimage = fmt->bytesperline * fmt->height; | ||
553 | |||
554 | vbi = &vv->vbi_fmt; | ||
555 | vbi->sampling_rate = 27000000; | ||
556 | vbi->offset = 248; /* todo */ | ||
557 | vbi->samples_per_line = 720 * 2; | ||
558 | vbi->sample_format = V4L2_PIX_FMT_GREY; | ||
559 | |||
560 | /* fixme: this only works for PAL */ | ||
561 | vbi->start[0] = 5; | ||
562 | vbi->count[0] = 16; | ||
563 | vbi->start[1] = 312; | ||
564 | vbi->count[1] = 16; | ||
565 | |||
566 | init_timer(&vv->vbi_read_timeout); | ||
567 | |||
568 | vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING; | ||
569 | vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY; | ||
570 | dev->vv_data = vv; | ||
571 | dev->vv_callback = &vv_callback; | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | EXPORT_SYMBOL_GPL(saa7146_vv_init); | ||
576 | |||
577 | int saa7146_vv_release(struct saa7146_dev* dev) | ||
578 | { | ||
579 | struct saa7146_vv *vv = dev->vv_data; | ||
580 | |||
581 | DEB_EE("dev:%p\n", dev); | ||
582 | |||
583 | v4l2_device_unregister(&dev->v4l2_dev); | ||
584 | pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); | ||
585 | v4l2_ctrl_handler_free(&dev->ctrl_handler); | ||
586 | kfree(vv); | ||
587 | dev->vv_data = NULL; | ||
588 | dev->vv_callback = NULL; | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | EXPORT_SYMBOL_GPL(saa7146_vv_release); | ||
593 | |||
594 | int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, | ||
595 | char *name, int type) | ||
596 | { | ||
597 | struct video_device *vfd; | ||
598 | int err; | ||
599 | int i; | ||
600 | |||
601 | DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type); | ||
602 | |||
603 | // released by vfd->release | ||
604 | vfd = video_device_alloc(); | ||
605 | if (vfd == NULL) | ||
606 | return -ENOMEM; | ||
607 | |||
608 | vfd->fops = &video_fops; | ||
609 | if (type == VFL_TYPE_GRABBER) | ||
610 | vfd->ioctl_ops = &dev->ext_vv_data->vid_ops; | ||
611 | else | ||
612 | vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops; | ||
613 | vfd->release = video_device_release; | ||
614 | vfd->lock = &dev->v4l2_lock; | ||
615 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
616 | vfd->tvnorms = 0; | ||
617 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
618 | for (i = 0; i < dev->ext_vv_data->num_stds; i++) | ||
619 | vfd->tvnorms |= dev->ext_vv_data->stds[i].id; | ||
620 | strlcpy(vfd->name, name, sizeof(vfd->name)); | ||
621 | video_set_drvdata(vfd, dev); | ||
622 | |||
623 | err = video_register_device(vfd, type, -1); | ||
624 | if (err < 0) { | ||
625 | ERR("cannot register v4l2 device. skipping.\n"); | ||
626 | video_device_release(vfd); | ||
627 | return err; | ||
628 | } | ||
629 | |||
630 | pr_info("%s: registered device %s [v4l2]\n", | ||
631 | dev->name, video_device_node_name(vfd)); | ||
632 | |||
633 | *vid = vfd; | ||
634 | return 0; | ||
635 | } | ||
636 | EXPORT_SYMBOL_GPL(saa7146_register_device); | ||
637 | |||
638 | int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) | ||
639 | { | ||
640 | DEB_EE("dev:%p\n", dev); | ||
641 | |||
642 | video_unregister_device(*vid); | ||
643 | *vid = NULL; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | EXPORT_SYMBOL_GPL(saa7146_unregister_device); | ||
648 | |||
649 | static int __init saa7146_vv_init_module(void) | ||
650 | { | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | |||
655 | static void __exit saa7146_vv_cleanup_module(void) | ||
656 | { | ||
657 | } | ||
658 | |||
659 | module_init(saa7146_vv_init_module); | ||
660 | module_exit(saa7146_vv_cleanup_module); | ||
661 | |||
662 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
663 | MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware"); | ||
664 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/saa7146/saa7146_hlp.c b/drivers/media/common/saa7146/saa7146_hlp.c deleted file mode 100644 index be746d1aee9..00000000000 --- a/drivers/media/common/saa7146/saa7146_hlp.c +++ /dev/null | |||
@@ -1,1048 +0,0 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/export.h> | ||
5 | #include <media/saa7146_vv.h> | ||
6 | |||
7 | static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format) | ||
8 | { | ||
9 | /* clear out the necessary bits */ | ||
10 | *clip_format &= 0x0000ffff; | ||
11 | /* set these bits new */ | ||
12 | *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16)); | ||
13 | } | ||
14 | |||
15 | static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl) | ||
16 | { | ||
17 | *hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28); | ||
18 | *hps_ctrl |= (source << 30) | (sync << 28); | ||
19 | } | ||
20 | |||
21 | static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl) | ||
22 | { | ||
23 | int hyo = 0, hxo = 0; | ||
24 | |||
25 | hyo = vv->standard->v_offset; | ||
26 | hxo = vv->standard->h_offset; | ||
27 | |||
28 | *hps_h_scale &= ~(MASK_B0 | 0xf00); | ||
29 | *hps_h_scale |= (hxo << 0); | ||
30 | |||
31 | *hps_ctrl &= ~(MASK_W0 | MASK_B2); | ||
32 | *hps_ctrl |= (hyo << 12); | ||
33 | } | ||
34 | |||
35 | /* helper functions for the calculation of the horizontal- and vertical | ||
36 | scaling registers, clip-format-register etc ... | ||
37 | these functions take pointers to the (most-likely read-out | ||
38 | original-values) and manipulate them according to the requested | ||
39 | changes. | ||
40 | */ | ||
41 | |||
42 | /* hps_coeff used for CXY and CXUV; scale 1/1 -> scale 1/64 */ | ||
43 | static struct { | ||
44 | u16 hps_coeff; | ||
45 | u16 weight_sum; | ||
46 | } hps_h_coeff_tab [] = { | ||
47 | {0x00, 2}, {0x02, 4}, {0x00, 4}, {0x06, 8}, {0x02, 8}, | ||
48 | {0x08, 8}, {0x00, 8}, {0x1E, 16}, {0x0E, 8}, {0x26, 8}, | ||
49 | {0x06, 8}, {0x42, 8}, {0x02, 8}, {0x80, 8}, {0x00, 8}, | ||
50 | {0xFE, 16}, {0xFE, 8}, {0x7E, 8}, {0x7E, 8}, {0x3E, 8}, | ||
51 | {0x3E, 8}, {0x1E, 8}, {0x1E, 8}, {0x0E, 8}, {0x0E, 8}, | ||
52 | {0x06, 8}, {0x06, 8}, {0x02, 8}, {0x02, 8}, {0x00, 8}, | ||
53 | {0x00, 8}, {0xFE, 16}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, | ||
54 | {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, | ||
55 | {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, | ||
56 | {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0xFE, 8}, {0x7E, 8}, | ||
57 | {0x7E, 8}, {0x3E, 8}, {0x3E, 8}, {0x1E, 8}, {0x1E, 8}, | ||
58 | {0x0E, 8}, {0x0E, 8}, {0x06, 8}, {0x06, 8}, {0x02, 8}, | ||
59 | {0x02, 8}, {0x00, 8}, {0x00, 8}, {0xFE, 16} | ||
60 | }; | ||
61 | |||
62 | /* table of attenuation values for horizontal scaling */ | ||
63 | static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0}; | ||
64 | |||
65 | /* calculate horizontal scale registers */ | ||
66 | static int calculate_h_scale_registers(struct saa7146_dev *dev, | ||
67 | int in_x, int out_x, int flip_lr, | ||
68 | u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale) | ||
69 | { | ||
70 | /* horizontal prescaler */ | ||
71 | u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0; | ||
72 | /* horizontal scaler */ | ||
73 | u32 xim = 0, xp = 0, xsci =0; | ||
74 | /* vertical scale & gain */ | ||
75 | u32 pfuv = 0; | ||
76 | |||
77 | /* helper variables */ | ||
78 | u32 h_atten = 0, i = 0; | ||
79 | |||
80 | if ( 0 == out_x ) { | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | /* mask out vanity-bit */ | ||
85 | *hps_ctrl &= ~MASK_29; | ||
86 | |||
87 | /* calculate prescale-(xspc)-value: [n .. 1/2) : 1 | ||
88 | [1/2 .. 1/3) : 2 | ||
89 | [1/3 .. 1/4) : 3 | ||
90 | ... */ | ||
91 | if (in_x > out_x) { | ||
92 | xpsc = in_x / out_x; | ||
93 | } | ||
94 | else { | ||
95 | /* zooming */ | ||
96 | xpsc = 1; | ||
97 | } | ||
98 | |||
99 | /* if flip_lr-bit is set, number of pixels after | ||
100 | horizontal prescaling must be < 384 */ | ||
101 | if ( 0 != flip_lr ) { | ||
102 | |||
103 | /* set vanity bit */ | ||
104 | *hps_ctrl |= MASK_29; | ||
105 | |||
106 | while (in_x / xpsc >= 384 ) | ||
107 | xpsc++; | ||
108 | } | ||
109 | /* if zooming is wanted, number of pixels after | ||
110 | horizontal prescaling must be < 768 */ | ||
111 | else { | ||
112 | while ( in_x / xpsc >= 768 ) | ||
113 | xpsc++; | ||
114 | } | ||
115 | |||
116 | /* maximum prescale is 64 (p.69) */ | ||
117 | if ( xpsc > 64 ) | ||
118 | xpsc = 64; | ||
119 | |||
120 | /* keep xacm clear*/ | ||
121 | xacm = 0; | ||
122 | |||
123 | /* set horizontal filter parameters (CXY = CXUV) */ | ||
124 | cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].hps_coeff; | ||
125 | cxuv = cxy; | ||
126 | |||
127 | /* calculate and set horizontal fine scale (xsci) */ | ||
128 | |||
129 | /* bypass the horizontal scaler ? */ | ||
130 | if ( (in_x == out_x) && ( 1 == xpsc ) ) | ||
131 | xsci = 0x400; | ||
132 | else | ||
133 | xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc; | ||
134 | |||
135 | /* set start phase for horizontal fine scale (xp) to 0 */ | ||
136 | xp = 0; | ||
137 | |||
138 | /* set xim, if we bypass the horizontal scaler */ | ||
139 | if ( 0x400 == xsci ) | ||
140 | xim = 1; | ||
141 | else | ||
142 | xim = 0; | ||
143 | |||
144 | /* if the prescaler is bypassed, enable horizontal | ||
145 | accumulation mode (xacm) and clear dcgx */ | ||
146 | if( 1 == xpsc ) { | ||
147 | xacm = 1; | ||
148 | dcgx = 0; | ||
149 | } else { | ||
150 | xacm = 0; | ||
151 | /* get best match in the table of attenuations | ||
152 | for horizontal scaling */ | ||
153 | h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].weight_sum; | ||
154 | |||
155 | for (i = 0; h_attenuation[i] != 0; i++) { | ||
156 | if (h_attenuation[i] >= h_atten) | ||
157 | break; | ||
158 | } | ||
159 | |||
160 | dcgx = i; | ||
161 | } | ||
162 | |||
163 | /* the horizontal scaling increment controls the UV filter | ||
164 | to reduce the bandwidth to improve the display quality, | ||
165 | so set it ... */ | ||
166 | if ( xsci == 0x400) | ||
167 | pfuv = 0x00; | ||
168 | else if ( xsci < 0x600) | ||
169 | pfuv = 0x01; | ||
170 | else if ( xsci < 0x680) | ||
171 | pfuv = 0x11; | ||
172 | else if ( xsci < 0x700) | ||
173 | pfuv = 0x22; | ||
174 | else | ||
175 | pfuv = 0x33; | ||
176 | |||
177 | |||
178 | *hps_v_gain &= MASK_W0|MASK_B2; | ||
179 | *hps_v_gain |= (pfuv << 24); | ||
180 | |||
181 | *hps_h_scale &= ~(MASK_W1 | 0xf000); | ||
182 | *hps_h_scale |= (xim << 31) | (xp << 24) | (xsci << 12); | ||
183 | |||
184 | *hps_h_prescale |= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static struct { | ||
190 | u16 hps_coeff; | ||
191 | u16 weight_sum; | ||
192 | } hps_v_coeff_tab [] = { | ||
193 | {0x0100, 2}, {0x0102, 4}, {0x0300, 4}, {0x0106, 8}, {0x0502, 8}, | ||
194 | {0x0708, 8}, {0x0F00, 8}, {0x011E, 16}, {0x110E, 16}, {0x1926, 16}, | ||
195 | {0x3906, 16}, {0x3D42, 16}, {0x7D02, 16}, {0x7F80, 16}, {0xFF00, 16}, | ||
196 | {0x01FE, 32}, {0x01FE, 32}, {0x817E, 32}, {0x817E, 32}, {0xC13E, 32}, | ||
197 | {0xC13E, 32}, {0xE11E, 32}, {0xE11E, 32}, {0xF10E, 32}, {0xF10E, 32}, | ||
198 | {0xF906, 32}, {0xF906, 32}, {0xFD02, 32}, {0xFD02, 32}, {0xFF00, 32}, | ||
199 | {0xFF00, 32}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, | ||
200 | {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, | ||
201 | {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, | ||
202 | {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x01FE, 64}, {0x817E, 64}, | ||
203 | {0x817E, 64}, {0xC13E, 64}, {0xC13E, 64}, {0xE11E, 64}, {0xE11E, 64}, | ||
204 | {0xF10E, 64}, {0xF10E, 64}, {0xF906, 64}, {0xF906, 64}, {0xFD02, 64}, | ||
205 | {0xFD02, 64}, {0xFF00, 64}, {0xFF00, 64}, {0x01FE, 128} | ||
206 | }; | ||
207 | |||
208 | /* table of attenuation values for vertical scaling */ | ||
209 | static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0}; | ||
210 | |||
211 | /* calculate vertical scale registers */ | ||
212 | static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field, | ||
213 | int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain) | ||
214 | { | ||
215 | int lpi = 0; | ||
216 | |||
217 | /* vertical scaling */ | ||
218 | u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0; | ||
219 | /* vertical scale & gain */ | ||
220 | u32 dcgy = 0, cya_cyb = 0; | ||
221 | |||
222 | /* helper variables */ | ||
223 | u32 v_atten = 0, i = 0; | ||
224 | |||
225 | /* error, if vertical zooming */ | ||
226 | if ( in_y < out_y ) { | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | |||
230 | /* linear phase interpolation may be used | ||
231 | if scaling is between 1 and 1/2 (both fields used) | ||
232 | or scaling is between 1/2 and 1/4 (if only one field is used) */ | ||
233 | |||
234 | if (V4L2_FIELD_HAS_BOTH(field)) { | ||
235 | if( 2*out_y >= in_y) { | ||
236 | lpi = 1; | ||
237 | } | ||
238 | } else if (field == V4L2_FIELD_TOP | ||
239 | || field == V4L2_FIELD_ALTERNATE | ||
240 | || field == V4L2_FIELD_BOTTOM) { | ||
241 | if( 4*out_y >= in_y ) { | ||
242 | lpi = 1; | ||
243 | } | ||
244 | out_y *= 2; | ||
245 | } | ||
246 | if( 0 != lpi ) { | ||
247 | |||
248 | yacm = 0; | ||
249 | yacl = 0; | ||
250 | cya_cyb = 0x00ff; | ||
251 | |||
252 | /* calculate scaling increment */ | ||
253 | if ( in_y > out_y ) | ||
254 | ysci = ((1024 * in_y) / (out_y + 1)) - 1024; | ||
255 | else | ||
256 | ysci = 0; | ||
257 | |||
258 | dcgy = 0; | ||
259 | |||
260 | /* calculate ype and ypo */ | ||
261 | ype = ysci / 16; | ||
262 | ypo = ype + (ysci / 64); | ||
263 | |||
264 | } else { | ||
265 | yacm = 1; | ||
266 | |||
267 | /* calculate scaling increment */ | ||
268 | ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10; | ||
269 | |||
270 | /* calculate ype and ypo */ | ||
271 | ypo = ype = ((ysci + 15) / 16); | ||
272 | |||
273 | /* the sequence length interval (yacl) has to be set according | ||
274 | to the prescale value, e.g. [n .. 1/2) : 0 | ||
275 | [1/2 .. 1/3) : 1 | ||
276 | [1/3 .. 1/4) : 2 | ||
277 | ... */ | ||
278 | if ( ysci < 512) { | ||
279 | yacl = 0; | ||
280 | } else { | ||
281 | yacl = ( ysci / (1024 - ysci) ); | ||
282 | } | ||
283 | |||
284 | /* get filter coefficients for cya, cyb from table hps_v_coeff_tab */ | ||
285 | cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].hps_coeff; | ||
286 | |||
287 | /* get best match in the table of attenuations for vertical scaling */ | ||
288 | v_atten = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].weight_sum; | ||
289 | |||
290 | for (i = 0; v_attenuation[i] != 0; i++) { | ||
291 | if (v_attenuation[i] >= v_atten) | ||
292 | break; | ||
293 | } | ||
294 | |||
295 | dcgy = i; | ||
296 | } | ||
297 | |||
298 | /* ypo and ype swapped in spec ? */ | ||
299 | *hps_v_scale |= (yacm << 31) | (ysci << 21) | (yacl << 15) | (ypo << 8 ) | (ype << 1); | ||
300 | |||
301 | *hps_v_gain &= ~(MASK_W0|MASK_B2); | ||
302 | *hps_v_gain |= (dcgy << 16) | (cya_cyb << 0); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | /* simple bubble-sort algorithm with duplicate elimination */ | ||
308 | static int sort_and_eliminate(u32* values, int* count) | ||
309 | { | ||
310 | int low = 0, high = 0, top = 0, temp = 0; | ||
311 | int cur = 0, next = 0; | ||
312 | |||
313 | /* sanity checks */ | ||
314 | if( (0 > *count) || (NULL == values) ) { | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | /* bubble sort the first @count items of the array @values */ | ||
319 | for( top = *count; top > 0; top--) { | ||
320 | for( low = 0, high = 1; high < top; low++, high++) { | ||
321 | if( values[low] > values[high] ) { | ||
322 | temp = values[low]; | ||
323 | values[low] = values[high]; | ||
324 | values[high] = temp; | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | |||
329 | /* remove duplicate items */ | ||
330 | for( cur = 0, next = 1; next < *count; next++) { | ||
331 | if( values[cur] != values[next]) | ||
332 | values[++cur] = values[next]; | ||
333 | } | ||
334 | |||
335 | *count = cur + 1; | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh, | ||
341 | struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field) | ||
342 | { | ||
343 | struct saa7146_vv *vv = dev->vv_data; | ||
344 | __le32 *clipping = vv->d_clipping.cpu_addr; | ||
345 | |||
346 | int width = vv->ov.win.w.width; | ||
347 | int height = vv->ov.win.w.height; | ||
348 | int clipcount = vv->ov.nclips; | ||
349 | |||
350 | u32 line_list[32]; | ||
351 | u32 pixel_list[32]; | ||
352 | int numdwords = 0; | ||
353 | |||
354 | int i = 0, j = 0; | ||
355 | int cnt_line = 0, cnt_pixel = 0; | ||
356 | |||
357 | int x[32], y[32], w[32], h[32]; | ||
358 | |||
359 | /* clear out memory */ | ||
360 | memset(&line_list[0], 0x00, sizeof(u32)*32); | ||
361 | memset(&pixel_list[0], 0x00, sizeof(u32)*32); | ||
362 | memset(clipping, 0x00, SAA7146_CLIPPING_MEM); | ||
363 | |||
364 | /* fill the line and pixel-lists */ | ||
365 | for(i = 0; i < clipcount; i++) { | ||
366 | int l = 0, r = 0, t = 0, b = 0; | ||
367 | |||
368 | x[i] = vv->ov.clips[i].c.left; | ||
369 | y[i] = vv->ov.clips[i].c.top; | ||
370 | w[i] = vv->ov.clips[i].c.width; | ||
371 | h[i] = vv->ov.clips[i].c.height; | ||
372 | |||
373 | if( w[i] < 0) { | ||
374 | x[i] += w[i]; w[i] = -w[i]; | ||
375 | } | ||
376 | if( h[i] < 0) { | ||
377 | y[i] += h[i]; h[i] = -h[i]; | ||
378 | } | ||
379 | if( x[i] < 0) { | ||
380 | w[i] += x[i]; x[i] = 0; | ||
381 | } | ||
382 | if( y[i] < 0) { | ||
383 | h[i] += y[i]; y[i] = 0; | ||
384 | } | ||
385 | if( 0 != vv->vflip ) { | ||
386 | y[i] = height - y[i] - h[i]; | ||
387 | } | ||
388 | |||
389 | l = x[i]; | ||
390 | r = x[i]+w[i]; | ||
391 | t = y[i]; | ||
392 | b = y[i]+h[i]; | ||
393 | |||
394 | /* insert left/right coordinates */ | ||
395 | pixel_list[ 2*i ] = min_t(int, l, width); | ||
396 | pixel_list[(2*i)+1] = min_t(int, r, width); | ||
397 | /* insert top/bottom coordinates */ | ||
398 | line_list[ 2*i ] = min_t(int, t, height); | ||
399 | line_list[(2*i)+1] = min_t(int, b, height); | ||
400 | } | ||
401 | |||
402 | /* sort and eliminate lists */ | ||
403 | cnt_line = cnt_pixel = 2*clipcount; | ||
404 | sort_and_eliminate( &pixel_list[0], &cnt_pixel ); | ||
405 | sort_and_eliminate( &line_list[0], &cnt_line ); | ||
406 | |||
407 | /* calculate the number of used u32s */ | ||
408 | numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2; | ||
409 | numdwords = max_t(int, 4, numdwords); | ||
410 | numdwords = min_t(int, 64, numdwords); | ||
411 | |||
412 | /* fill up cliptable */ | ||
413 | for(i = 0; i < cnt_pixel; i++) { | ||
414 | clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16); | ||
415 | } | ||
416 | for(i = 0; i < cnt_line; i++) { | ||
417 | clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16); | ||
418 | } | ||
419 | |||
420 | /* fill up cliptable with the display infos */ | ||
421 | for(j = 0; j < clipcount; j++) { | ||
422 | |||
423 | for(i = 0; i < cnt_pixel; i++) { | ||
424 | |||
425 | if( x[j] < 0) | ||
426 | x[j] = 0; | ||
427 | |||
428 | if( pixel_list[i] < (x[j] + w[j])) { | ||
429 | |||
430 | if ( pixel_list[i] >= x[j] ) { | ||
431 | clipping[2*i] |= cpu_to_le32(1 << j); | ||
432 | } | ||
433 | } | ||
434 | } | ||
435 | for(i = 0; i < cnt_line; i++) { | ||
436 | |||
437 | if( y[j] < 0) | ||
438 | y[j] = 0; | ||
439 | |||
440 | if( line_list[i] < (y[j] + h[j]) ) { | ||
441 | |||
442 | if( line_list[i] >= y[j] ) { | ||
443 | clipping[(2*i)+1] |= cpu_to_le32(1 << j); | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | } | ||
448 | |||
449 | /* adjust arbitration control register */ | ||
450 | *arbtr_ctrl &= 0xffff00ff; | ||
451 | *arbtr_ctrl |= 0x00001c00; | ||
452 | |||
453 | vdma2->base_even = vv->d_clipping.dma_handle; | ||
454 | vdma2->base_odd = vv->d_clipping.dma_handle; | ||
455 | vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords)); | ||
456 | vdma2->base_page = 0x04; | ||
457 | vdma2->pitch = 0x00; | ||
458 | vdma2->num_line_byte = (0 << 16 | (sizeof(u32))*(numdwords-1) ); | ||
459 | |||
460 | /* set clipping-mode. this depends on the field(s) used */ | ||
461 | *clip_format &= 0xfffffff7; | ||
462 | if (V4L2_FIELD_HAS_BOTH(field)) { | ||
463 | *clip_format |= 0x00000008; | ||
464 | } else { | ||
465 | *clip_format |= 0x00000000; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | /* disable clipping */ | ||
470 | static void saa7146_disable_clipping(struct saa7146_dev *dev) | ||
471 | { | ||
472 | u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); | ||
473 | |||
474 | /* mask out relevant bits (=lower word)*/ | ||
475 | clip_format &= MASK_W1; | ||
476 | |||
477 | /* upload clipping-registers*/ | ||
478 | saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format); | ||
479 | saa7146_write(dev, MC2, (MASK_05 | MASK_21)); | ||
480 | |||
481 | /* disable video dma2 */ | ||
482 | saa7146_write(dev, MC1, MASK_21); | ||
483 | } | ||
484 | |||
485 | static void saa7146_set_clipping_rect(struct saa7146_fh *fh) | ||
486 | { | ||
487 | struct saa7146_dev *dev = fh->dev; | ||
488 | struct saa7146_vv *vv = dev->vv_data; | ||
489 | enum v4l2_field field = vv->ov.win.field; | ||
490 | struct saa7146_video_dma vdma2; | ||
491 | u32 clip_format; | ||
492 | u32 arbtr_ctrl; | ||
493 | |||
494 | /* check clipcount, disable clipping if clipcount == 0*/ | ||
495 | if (vv->ov.nclips == 0) { | ||
496 | saa7146_disable_clipping(dev); | ||
497 | return; | ||
498 | } | ||
499 | |||
500 | clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); | ||
501 | arbtr_ctrl = saa7146_read(dev, PCI_BT_V1); | ||
502 | |||
503 | calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field); | ||
504 | |||
505 | /* set clipping format */ | ||
506 | clip_format &= 0xffff0008; | ||
507 | clip_format |= (SAA7146_CLIPPING_RECT << 4); | ||
508 | |||
509 | /* prepare video dma2 */ | ||
510 | saa7146_write(dev, BASE_EVEN2, vdma2.base_even); | ||
511 | saa7146_write(dev, BASE_ODD2, vdma2.base_odd); | ||
512 | saa7146_write(dev, PROT_ADDR2, vdma2.prot_addr); | ||
513 | saa7146_write(dev, BASE_PAGE2, vdma2.base_page); | ||
514 | saa7146_write(dev, PITCH2, vdma2.pitch); | ||
515 | saa7146_write(dev, NUM_LINE_BYTE2, vdma2.num_line_byte); | ||
516 | |||
517 | /* prepare the rest */ | ||
518 | saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format); | ||
519 | saa7146_write(dev, PCI_BT_V1, arbtr_ctrl); | ||
520 | |||
521 | /* upload clip_control-register, clipping-registers, enable video dma2 */ | ||
522 | saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19)); | ||
523 | saa7146_write(dev, MC1, (MASK_05 | MASK_21)); | ||
524 | } | ||
525 | |||
526 | static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field) | ||
527 | { | ||
528 | struct saa7146_vv *vv = dev->vv_data; | ||
529 | |||
530 | int source = vv->current_hps_source; | ||
531 | int sync = vv->current_hps_sync; | ||
532 | |||
533 | u32 hps_v_scale = 0, hps_v_gain = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0; | ||
534 | |||
535 | /* set vertical scale */ | ||
536 | hps_v_scale = 0; /* all bits get set by the function-call */ | ||
537 | hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/ | ||
538 | calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain); | ||
539 | |||
540 | /* set horizontal scale */ | ||
541 | hps_ctrl = 0; | ||
542 | hps_h_prescale = 0; /* all bits get set in the function */ | ||
543 | hps_h_scale = 0; | ||
544 | calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale); | ||
545 | |||
546 | /* set hyo and hxo */ | ||
547 | calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl); | ||
548 | calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl); | ||
549 | |||
550 | /* write out new register contents */ | ||
551 | saa7146_write(dev, HPS_V_SCALE, hps_v_scale); | ||
552 | saa7146_write(dev, HPS_V_GAIN, hps_v_gain); | ||
553 | saa7146_write(dev, HPS_CTRL, hps_ctrl); | ||
554 | saa7146_write(dev, HPS_H_PRESCALE,hps_h_prescale); | ||
555 | saa7146_write(dev, HPS_H_SCALE, hps_h_scale); | ||
556 | |||
557 | /* upload shadow-ram registers */ | ||
558 | saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) ); | ||
559 | } | ||
560 | |||
561 | /* calculate the new memory offsets for a desired position */ | ||
562 | static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat) | ||
563 | { | ||
564 | struct saa7146_vv *vv = dev->vv_data; | ||
565 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat); | ||
566 | |||
567 | int b_depth = vv->ov_fmt->depth; | ||
568 | int b_bpl = vv->ov_fb.fmt.bytesperline; | ||
569 | /* The unsigned long cast is to remove a 64-bit compile warning since | ||
570 | it looks like a 64-bit address is cast to a 32-bit value, even | ||
571 | though the base pointer is really a 32-bit physical address that | ||
572 | goes into a 32-bit DMA register. | ||
573 | FIXME: might not work on some 64-bit platforms, but see the FIXME | ||
574 | in struct v4l2_framebuffer (videodev2.h) for that. | ||
575 | */ | ||
576 | u32 base = (u32)(unsigned long)vv->ov_fb.base; | ||
577 | |||
578 | struct saa7146_video_dma vdma1; | ||
579 | |||
580 | /* calculate memory offsets for picture, look if we shall top-down-flip */ | ||
581 | vdma1.pitch = 2*b_bpl; | ||
582 | if ( 0 == vv->vflip ) { | ||
583 | vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); | ||
584 | vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2); | ||
585 | vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2)); | ||
586 | } | ||
587 | else { | ||
588 | vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); | ||
589 | vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2); | ||
590 | vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2)); | ||
591 | } | ||
592 | |||
593 | if (V4L2_FIELD_HAS_BOTH(field)) { | ||
594 | } else if (field == V4L2_FIELD_ALTERNATE) { | ||
595 | /* fixme */ | ||
596 | vdma1.base_odd = vdma1.prot_addr; | ||
597 | vdma1.pitch /= 2; | ||
598 | } else if (field == V4L2_FIELD_TOP) { | ||
599 | vdma1.base_odd = vdma1.prot_addr; | ||
600 | vdma1.pitch /= 2; | ||
601 | } else if (field == V4L2_FIELD_BOTTOM) { | ||
602 | vdma1.base_odd = vdma1.base_even; | ||
603 | vdma1.base_even = vdma1.prot_addr; | ||
604 | vdma1.pitch /= 2; | ||
605 | } | ||
606 | |||
607 | if ( 0 != vv->vflip ) { | ||
608 | vdma1.pitch *= -1; | ||
609 | } | ||
610 | |||
611 | vdma1.base_page = sfmt->swap; | ||
612 | vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels; | ||
613 | |||
614 | saa7146_write_out_dma(dev, 1, &vdma1); | ||
615 | } | ||
616 | |||
617 | static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette) | ||
618 | { | ||
619 | u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); | ||
620 | |||
621 | /* call helper function */ | ||
622 | calculate_output_format_register(dev,palette,&clip_format); | ||
623 | |||
624 | /* update the hps registers */ | ||
625 | saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format); | ||
626 | saa7146_write(dev, MC2, (MASK_05 | MASK_21)); | ||
627 | } | ||
628 | |||
629 | /* select input-source */ | ||
630 | void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync) | ||
631 | { | ||
632 | struct saa7146_vv *vv = dev->vv_data; | ||
633 | u32 hps_ctrl = 0; | ||
634 | |||
635 | /* read old state */ | ||
636 | hps_ctrl = saa7146_read(dev, HPS_CTRL); | ||
637 | |||
638 | hps_ctrl &= ~( MASK_31 | MASK_30 | MASK_28 ); | ||
639 | hps_ctrl |= (source << 30) | (sync << 28); | ||
640 | |||
641 | /* write back & upload register */ | ||
642 | saa7146_write(dev, HPS_CTRL, hps_ctrl); | ||
643 | saa7146_write(dev, MC2, (MASK_05 | MASK_21)); | ||
644 | |||
645 | vv->current_hps_source = source; | ||
646 | vv->current_hps_sync = sync; | ||
647 | } | ||
648 | EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); | ||
649 | |||
650 | int saa7146_enable_overlay(struct saa7146_fh *fh) | ||
651 | { | ||
652 | struct saa7146_dev *dev = fh->dev; | ||
653 | struct saa7146_vv *vv = dev->vv_data; | ||
654 | |||
655 | saa7146_set_window(dev, vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.field); | ||
656 | saa7146_set_position(dev, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov.win.w.height, vv->ov.win.field, vv->ov_fmt->pixelformat); | ||
657 | saa7146_set_output_format(dev, vv->ov_fmt->trans); | ||
658 | saa7146_set_clipping_rect(fh); | ||
659 | |||
660 | /* enable video dma1 */ | ||
661 | saa7146_write(dev, MC1, (MASK_06 | MASK_22)); | ||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | void saa7146_disable_overlay(struct saa7146_fh *fh) | ||
666 | { | ||
667 | struct saa7146_dev *dev = fh->dev; | ||
668 | |||
669 | /* disable clipping + video dma1 */ | ||
670 | saa7146_disable_clipping(dev); | ||
671 | saa7146_write(dev, MC1, MASK_22); | ||
672 | } | ||
673 | |||
674 | void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) | ||
675 | { | ||
676 | int where = 0; | ||
677 | |||
678 | if( which < 1 || which > 3) { | ||
679 | return; | ||
680 | } | ||
681 | |||
682 | /* calculate starting address */ | ||
683 | where = (which-1)*0x18; | ||
684 | |||
685 | saa7146_write(dev, where, vdma->base_odd); | ||
686 | saa7146_write(dev, where+0x04, vdma->base_even); | ||
687 | saa7146_write(dev, where+0x08, vdma->prot_addr); | ||
688 | saa7146_write(dev, where+0x0c, vdma->pitch); | ||
689 | saa7146_write(dev, where+0x10, vdma->base_page); | ||
690 | saa7146_write(dev, where+0x14, vdma->num_line_byte); | ||
691 | |||
692 | /* upload */ | ||
693 | saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1))); | ||
694 | /* | ||
695 | printk("vdma%d.base_even: 0x%08x\n", which,vdma->base_even); | ||
696 | printk("vdma%d.base_odd: 0x%08x\n", which,vdma->base_odd); | ||
697 | printk("vdma%d.prot_addr: 0x%08x\n", which,vdma->prot_addr); | ||
698 | printk("vdma%d.base_page: 0x%08x\n", which,vdma->base_page); | ||
699 | printk("vdma%d.pitch: 0x%08x\n", which,vdma->pitch); | ||
700 | printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte); | ||
701 | */ | ||
702 | } | ||
703 | |||
704 | static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf) | ||
705 | { | ||
706 | struct saa7146_vv *vv = dev->vv_data; | ||
707 | struct saa7146_video_dma vdma1; | ||
708 | |||
709 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); | ||
710 | |||
711 | int width = buf->fmt->width; | ||
712 | int height = buf->fmt->height; | ||
713 | int bytesperline = buf->fmt->bytesperline; | ||
714 | enum v4l2_field field = buf->fmt->field; | ||
715 | |||
716 | int depth = sfmt->depth; | ||
717 | |||
718 | DEB_CAP("[size=%dx%d,fields=%s]\n", | ||
719 | width, height, v4l2_field_names[field]); | ||
720 | |||
721 | if( bytesperline != 0) { | ||
722 | vdma1.pitch = bytesperline*2; | ||
723 | } else { | ||
724 | vdma1.pitch = (width*depth*2)/8; | ||
725 | } | ||
726 | vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); | ||
727 | vdma1.base_page = buf->pt[0].dma | ME1 | sfmt->swap; | ||
728 | |||
729 | if( 0 != vv->vflip ) { | ||
730 | vdma1.prot_addr = buf->pt[0].offset; | ||
731 | vdma1.base_even = buf->pt[0].offset+(vdma1.pitch/2)*height; | ||
732 | vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2); | ||
733 | } else { | ||
734 | vdma1.base_even = buf->pt[0].offset; | ||
735 | vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2); | ||
736 | vdma1.prot_addr = buf->pt[0].offset+(vdma1.pitch/2)*height; | ||
737 | } | ||
738 | |||
739 | if (V4L2_FIELD_HAS_BOTH(field)) { | ||
740 | } else if (field == V4L2_FIELD_ALTERNATE) { | ||
741 | /* fixme */ | ||
742 | if ( vv->last_field == V4L2_FIELD_TOP ) { | ||
743 | vdma1.base_odd = vdma1.prot_addr; | ||
744 | vdma1.pitch /= 2; | ||
745 | } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) { | ||
746 | vdma1.base_odd = vdma1.base_even; | ||
747 | vdma1.base_even = vdma1.prot_addr; | ||
748 | vdma1.pitch /= 2; | ||
749 | } | ||
750 | } else if (field == V4L2_FIELD_TOP) { | ||
751 | vdma1.base_odd = vdma1.prot_addr; | ||
752 | vdma1.pitch /= 2; | ||
753 | } else if (field == V4L2_FIELD_BOTTOM) { | ||
754 | vdma1.base_odd = vdma1.base_even; | ||
755 | vdma1.base_even = vdma1.prot_addr; | ||
756 | vdma1.pitch /= 2; | ||
757 | } | ||
758 | |||
759 | if( 0 != vv->vflip ) { | ||
760 | vdma1.pitch *= -1; | ||
761 | } | ||
762 | |||
763 | saa7146_write_out_dma(dev, 1, &vdma1); | ||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) | ||
768 | { | ||
769 | int height = buf->fmt->height; | ||
770 | int width = buf->fmt->width; | ||
771 | |||
772 | vdma2->pitch = width; | ||
773 | vdma3->pitch = width; | ||
774 | |||
775 | /* fixme: look at bytesperline! */ | ||
776 | |||
777 | if( 0 != vv->vflip ) { | ||
778 | vdma2->prot_addr = buf->pt[1].offset; | ||
779 | vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[1].offset; | ||
780 | vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2); | ||
781 | |||
782 | vdma3->prot_addr = buf->pt[2].offset; | ||
783 | vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[2].offset; | ||
784 | vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2); | ||
785 | } else { | ||
786 | vdma3->base_even = buf->pt[2].offset; | ||
787 | vdma3->base_odd = vdma3->base_even + (vdma3->pitch/2); | ||
788 | vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset; | ||
789 | |||
790 | vdma2->base_even = buf->pt[1].offset; | ||
791 | vdma2->base_odd = vdma2->base_even + (vdma2->pitch/2); | ||
792 | vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset; | ||
793 | } | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) | ||
799 | { | ||
800 | int height = buf->fmt->height; | ||
801 | int width = buf->fmt->width; | ||
802 | |||
803 | vdma2->pitch = width/2; | ||
804 | vdma3->pitch = width/2; | ||
805 | |||
806 | if( 0 != vv->vflip ) { | ||
807 | vdma2->prot_addr = buf->pt[2].offset; | ||
808 | vdma2->base_even = ((vdma2->pitch/2)*height)+buf->pt[2].offset; | ||
809 | vdma2->base_odd = vdma2->base_even - (vdma2->pitch/2); | ||
810 | |||
811 | vdma3->prot_addr = buf->pt[1].offset; | ||
812 | vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[1].offset; | ||
813 | vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2); | ||
814 | |||
815 | } else { | ||
816 | vdma3->base_even = buf->pt[2].offset; | ||
817 | vdma3->base_odd = vdma3->base_even + (vdma3->pitch); | ||
818 | vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset; | ||
819 | |||
820 | vdma2->base_even = buf->pt[1].offset; | ||
821 | vdma2->base_odd = vdma2->base_even + (vdma2->pitch); | ||
822 | vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset; | ||
823 | } | ||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf) | ||
828 | { | ||
829 | struct saa7146_vv *vv = dev->vv_data; | ||
830 | struct saa7146_video_dma vdma1; | ||
831 | struct saa7146_video_dma vdma2; | ||
832 | struct saa7146_video_dma vdma3; | ||
833 | |||
834 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); | ||
835 | |||
836 | int width = buf->fmt->width; | ||
837 | int height = buf->fmt->height; | ||
838 | enum v4l2_field field = buf->fmt->field; | ||
839 | |||
840 | BUG_ON(0 == buf->pt[0].dma); | ||
841 | BUG_ON(0 == buf->pt[1].dma); | ||
842 | BUG_ON(0 == buf->pt[2].dma); | ||
843 | |||
844 | DEB_CAP("[size=%dx%d,fields=%s]\n", | ||
845 | width, height, v4l2_field_names[field]); | ||
846 | |||
847 | /* fixme: look at bytesperline! */ | ||
848 | |||
849 | /* fixme: what happens for user space buffers here?. The offsets are | ||
850 | most likely wrong, this version here only works for page-aligned | ||
851 | buffers, modifications to the pagetable-functions are necessary...*/ | ||
852 | |||
853 | vdma1.pitch = width*2; | ||
854 | vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); | ||
855 | vdma1.base_page = buf->pt[0].dma | ME1; | ||
856 | |||
857 | if( 0 != vv->vflip ) { | ||
858 | vdma1.prot_addr = buf->pt[0].offset; | ||
859 | vdma1.base_even = ((vdma1.pitch/2)*height)+buf->pt[0].offset; | ||
860 | vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2); | ||
861 | } else { | ||
862 | vdma1.base_even = buf->pt[0].offset; | ||
863 | vdma1.base_odd = vdma1.base_even + (vdma1.pitch/2); | ||
864 | vdma1.prot_addr = (vdma1.pitch/2)*height+buf->pt[0].offset; | ||
865 | } | ||
866 | |||
867 | vdma2.num_line_byte = 0; /* unused */ | ||
868 | vdma2.base_page = buf->pt[1].dma | ME1; | ||
869 | |||
870 | vdma3.num_line_byte = 0; /* unused */ | ||
871 | vdma3.base_page = buf->pt[2].dma | ME1; | ||
872 | |||
873 | switch( sfmt->depth ) { | ||
874 | case 12: { | ||
875 | calc_planar_420(vv,buf,&vdma2,&vdma3); | ||
876 | break; | ||
877 | } | ||
878 | case 16: { | ||
879 | calc_planar_422(vv,buf,&vdma2,&vdma3); | ||
880 | break; | ||
881 | } | ||
882 | default: { | ||
883 | return -1; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | if (V4L2_FIELD_HAS_BOTH(field)) { | ||
888 | } else if (field == V4L2_FIELD_ALTERNATE) { | ||
889 | /* fixme */ | ||
890 | vdma1.base_odd = vdma1.prot_addr; | ||
891 | vdma1.pitch /= 2; | ||
892 | vdma2.base_odd = vdma2.prot_addr; | ||
893 | vdma2.pitch /= 2; | ||
894 | vdma3.base_odd = vdma3.prot_addr; | ||
895 | vdma3.pitch /= 2; | ||
896 | } else if (field == V4L2_FIELD_TOP) { | ||
897 | vdma1.base_odd = vdma1.prot_addr; | ||
898 | vdma1.pitch /= 2; | ||
899 | vdma2.base_odd = vdma2.prot_addr; | ||
900 | vdma2.pitch /= 2; | ||
901 | vdma3.base_odd = vdma3.prot_addr; | ||
902 | vdma3.pitch /= 2; | ||
903 | } else if (field == V4L2_FIELD_BOTTOM) { | ||
904 | vdma1.base_odd = vdma1.base_even; | ||
905 | vdma1.base_even = vdma1.prot_addr; | ||
906 | vdma1.pitch /= 2; | ||
907 | vdma2.base_odd = vdma2.base_even; | ||
908 | vdma2.base_even = vdma2.prot_addr; | ||
909 | vdma2.pitch /= 2; | ||
910 | vdma3.base_odd = vdma3.base_even; | ||
911 | vdma3.base_even = vdma3.prot_addr; | ||
912 | vdma3.pitch /= 2; | ||
913 | } | ||
914 | |||
915 | if( 0 != vv->vflip ) { | ||
916 | vdma1.pitch *= -1; | ||
917 | vdma2.pitch *= -1; | ||
918 | vdma3.pitch *= -1; | ||
919 | } | ||
920 | |||
921 | saa7146_write_out_dma(dev, 1, &vdma1); | ||
922 | if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) { | ||
923 | saa7146_write_out_dma(dev, 3, &vdma2); | ||
924 | saa7146_write_out_dma(dev, 2, &vdma3); | ||
925 | } else { | ||
926 | saa7146_write_out_dma(dev, 2, &vdma2); | ||
927 | saa7146_write_out_dma(dev, 3, &vdma3); | ||
928 | } | ||
929 | return 0; | ||
930 | } | ||
931 | |||
932 | static void program_capture_engine(struct saa7146_dev *dev, int planar) | ||
933 | { | ||
934 | struct saa7146_vv *vv = dev->vv_data; | ||
935 | int count = 0; | ||
936 | |||
937 | unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; | ||
938 | unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; | ||
939 | |||
940 | /* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/ | ||
941 | WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait); | ||
942 | WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait); | ||
943 | |||
944 | /* set rps register 0 */ | ||
945 | WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4)); | ||
946 | WRITE_RPS0(MASK_27 | MASK_11); | ||
947 | |||
948 | /* turn on video-dma1 */ | ||
949 | WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); | ||
950 | WRITE_RPS0(MASK_06 | MASK_22); /* => mask */ | ||
951 | WRITE_RPS0(MASK_06 | MASK_22); /* => values */ | ||
952 | if( 0 != planar ) { | ||
953 | /* turn on video-dma2 */ | ||
954 | WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); | ||
955 | WRITE_RPS0(MASK_05 | MASK_21); /* => mask */ | ||
956 | WRITE_RPS0(MASK_05 | MASK_21); /* => values */ | ||
957 | |||
958 | /* turn on video-dma3 */ | ||
959 | WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); | ||
960 | WRITE_RPS0(MASK_04 | MASK_20); /* => mask */ | ||
961 | WRITE_RPS0(MASK_04 | MASK_20); /* => values */ | ||
962 | } | ||
963 | |||
964 | /* wait for o_fid_a/b / e_fid_a/b toggle */ | ||
965 | if ( vv->last_field == V4L2_FIELD_INTERLACED ) { | ||
966 | WRITE_RPS0(CMD_PAUSE | o_wait); | ||
967 | WRITE_RPS0(CMD_PAUSE | e_wait); | ||
968 | } else if ( vv->last_field == V4L2_FIELD_TOP ) { | ||
969 | WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09)); | ||
970 | WRITE_RPS0(CMD_PAUSE | o_wait); | ||
971 | } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) { | ||
972 | WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09)); | ||
973 | WRITE_RPS0(CMD_PAUSE | e_wait); | ||
974 | } | ||
975 | |||
976 | /* turn off video-dma1 */ | ||
977 | WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); | ||
978 | WRITE_RPS0(MASK_22 | MASK_06); /* => mask */ | ||
979 | WRITE_RPS0(MASK_22); /* => values */ | ||
980 | if( 0 != planar ) { | ||
981 | /* turn off video-dma2 */ | ||
982 | WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); | ||
983 | WRITE_RPS0(MASK_05 | MASK_21); /* => mask */ | ||
984 | WRITE_RPS0(MASK_21); /* => values */ | ||
985 | |||
986 | /* turn off video-dma3 */ | ||
987 | WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); | ||
988 | WRITE_RPS0(MASK_04 | MASK_20); /* => mask */ | ||
989 | WRITE_RPS0(MASK_20); /* => values */ | ||
990 | } | ||
991 | |||
992 | /* generate interrupt */ | ||
993 | WRITE_RPS0(CMD_INTERRUPT); | ||
994 | |||
995 | /* stop */ | ||
996 | WRITE_RPS0(CMD_STOP); | ||
997 | } | ||
998 | |||
999 | void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) | ||
1000 | { | ||
1001 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); | ||
1002 | struct saa7146_vv *vv = dev->vv_data; | ||
1003 | u32 vdma1_prot_addr; | ||
1004 | |||
1005 | DEB_CAP("buf:%p, next:%p\n", buf, next); | ||
1006 | |||
1007 | vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1); | ||
1008 | if( 0 == vdma1_prot_addr ) { | ||
1009 | /* clear out beginning of streaming bit (rps register 0)*/ | ||
1010 | DEB_CAP("forcing sync to new frame\n"); | ||
1011 | saa7146_write(dev, MC2, MASK_27 ); | ||
1012 | } | ||
1013 | |||
1014 | saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field); | ||
1015 | saa7146_set_output_format(dev, sfmt->trans); | ||
1016 | saa7146_disable_clipping(dev); | ||
1017 | |||
1018 | if ( vv->last_field == V4L2_FIELD_INTERLACED ) { | ||
1019 | } else if ( vv->last_field == V4L2_FIELD_TOP ) { | ||
1020 | vv->last_field = V4L2_FIELD_BOTTOM; | ||
1021 | } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) { | ||
1022 | vv->last_field = V4L2_FIELD_TOP; | ||
1023 | } | ||
1024 | |||
1025 | if( 0 != IS_PLANAR(sfmt->trans)) { | ||
1026 | calculate_video_dma_grab_planar(dev, buf); | ||
1027 | program_capture_engine(dev,1); | ||
1028 | } else { | ||
1029 | calculate_video_dma_grab_packed(dev, buf); | ||
1030 | program_capture_engine(dev,0); | ||
1031 | } | ||
1032 | |||
1033 | /* | ||
1034 | printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1)); | ||
1035 | printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1)); | ||
1036 | printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1)); | ||
1037 | printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1)); | ||
1038 | printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1)); | ||
1039 | printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1)); | ||
1040 | printk("vdma%d => vptr : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1)); | ||
1041 | */ | ||
1042 | |||
1043 | /* write the address of the rps-program */ | ||
1044 | saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle); | ||
1045 | |||
1046 | /* turn on rps */ | ||
1047 | saa7146_write(dev, MC1, (MASK_12 | MASK_28)); | ||
1048 | } | ||
diff --git a/drivers/media/common/saa7146/saa7146_i2c.c b/drivers/media/common/saa7146/saa7146_i2c.c deleted file mode 100644 index 22027198129..00000000000 --- a/drivers/media/common/saa7146/saa7146_i2c.c +++ /dev/null | |||
@@ -1,423 +0,0 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
3 | #include <media/saa7146_vv.h> | ||
4 | |||
5 | static u32 saa7146_i2c_func(struct i2c_adapter *adapter) | ||
6 | { | ||
7 | /* DEB_I2C("'%s'\n", adapter->name); */ | ||
8 | |||
9 | return I2C_FUNC_I2C | ||
10 | | I2C_FUNC_SMBUS_QUICK | ||
11 | | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE | ||
12 | | I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; | ||
13 | } | ||
14 | |||
15 | /* this function returns the status-register of our i2c-device */ | ||
16 | static inline u32 saa7146_i2c_status(struct saa7146_dev *dev) | ||
17 | { | ||
18 | u32 iicsta = saa7146_read(dev, I2C_STATUS); | ||
19 | /* DEB_I2C("status: 0x%08x\n", iicsta); */ | ||
20 | return iicsta; | ||
21 | } | ||
22 | |||
23 | /* this function runs through the i2c-messages and prepares the data to be | ||
24 | sent through the saa7146. have a look at the specifications p. 122 ff | ||
25 | to understand this. it returns the number of u32s to send, or -1 | ||
26 | in case of an error. */ | ||
27 | static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op) | ||
28 | { | ||
29 | int h1, h2; | ||
30 | int i, j, addr; | ||
31 | int mem = 0, op_count = 0; | ||
32 | |||
33 | /* first determine size of needed memory */ | ||
34 | for(i = 0; i < num; i++) { | ||
35 | mem += m[i].len + 1; | ||
36 | } | ||
37 | |||
38 | /* worst case: we need one u32 for three bytes to be send | ||
39 | plus one extra byte to address the device */ | ||
40 | mem = 1 + ((mem-1) / 3); | ||
41 | |||
42 | /* we assume that op points to a memory of at least | ||
43 | * SAA7146_I2C_MEM bytes size. if we exceed this limit... | ||
44 | */ | ||
45 | if ((4 * mem) > SAA7146_I2C_MEM) { | ||
46 | /* DEB_I2C("cannot prepare i2c-message\n"); */ | ||
47 | return -ENOMEM; | ||
48 | } | ||
49 | |||
50 | /* be careful: clear out the i2c-mem first */ | ||
51 | memset(op,0,sizeof(__le32)*mem); | ||
52 | |||
53 | /* loop through all messages */ | ||
54 | for(i = 0; i < num; i++) { | ||
55 | |||
56 | /* insert the address of the i2c-slave. | ||
57 | note: we get 7 bit i2c-addresses, | ||
58 | so we have to perform a translation */ | ||
59 | addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0); | ||
60 | h1 = op_count/3; h2 = op_count%3; | ||
61 | op[h1] |= cpu_to_le32( (u8)addr << ((3-h2)*8)); | ||
62 | op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2)); | ||
63 | op_count++; | ||
64 | |||
65 | /* loop through all bytes of message i */ | ||
66 | for(j = 0; j < m[i].len; j++) { | ||
67 | /* insert the data bytes */ | ||
68 | h1 = op_count/3; h2 = op_count%3; | ||
69 | op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8)); | ||
70 | op[h1] |= cpu_to_le32( SAA7146_I2C_CONT << ((3-h2)*2)); | ||
71 | op_count++; | ||
72 | } | ||
73 | |||
74 | } | ||
75 | |||
76 | /* have a look at the last byte inserted: | ||
77 | if it was: ...CONT change it to ...STOP */ | ||
78 | h1 = (op_count-1)/3; h2 = (op_count-1)%3; | ||
79 | if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) { | ||
80 | op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2)); | ||
81 | op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2)); | ||
82 | } | ||
83 | |||
84 | /* return the number of u32s to send */ | ||
85 | return mem; | ||
86 | } | ||
87 | |||
88 | /* this functions loops through all i2c-messages. normally, it should determine | ||
89 | which bytes were read through the adapter and write them back to the corresponding | ||
90 | i2c-message. but instead, we simply write back all bytes. | ||
91 | fixme: this could be improved. */ | ||
92 | static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op) | ||
93 | { | ||
94 | int i, j; | ||
95 | int op_count = 0; | ||
96 | |||
97 | /* loop through all messages */ | ||
98 | for(i = 0; i < num; i++) { | ||
99 | |||
100 | op_count++; | ||
101 | |||
102 | /* loop through all bytes of message i */ | ||
103 | for(j = 0; j < m[i].len; j++) { | ||
104 | /* write back all bytes that could have been read */ | ||
105 | m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8)); | ||
106 | op_count++; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */ | ||
114 | static int saa7146_i2c_reset(struct saa7146_dev *dev) | ||
115 | { | ||
116 | /* get current status */ | ||
117 | u32 status = saa7146_i2c_status(dev); | ||
118 | |||
119 | /* clear registers for sure */ | ||
120 | saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); | ||
121 | saa7146_write(dev, I2C_TRANSFER, 0); | ||
122 | |||
123 | /* check if any operation is still in progress */ | ||
124 | if ( 0 != ( status & SAA7146_I2C_BUSY) ) { | ||
125 | |||
126 | /* yes, kill ongoing operation */ | ||
127 | DEB_I2C("busy_state detected\n"); | ||
128 | |||
129 | /* set "ABORT-OPERATION"-bit (bit 7)*/ | ||
130 | saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07)); | ||
131 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
132 | msleep(SAA7146_I2C_DELAY); | ||
133 | |||
134 | /* clear all error-bits pending; this is needed because p.123, note 1 */ | ||
135 | saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); | ||
136 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
137 | msleep(SAA7146_I2C_DELAY); | ||
138 | } | ||
139 | |||
140 | /* check if any error is (still) present. (this can be necessary because p.123, note 1) */ | ||
141 | status = saa7146_i2c_status(dev); | ||
142 | |||
143 | if ( dev->i2c_bitrate != status ) { | ||
144 | |||
145 | DEB_I2C("error_state detected. status:0x%08x\n", status); | ||
146 | |||
147 | /* Repeat the abort operation. This seems to be necessary | ||
148 | after serious protocol errors caused by e.g. the SAA7740 */ | ||
149 | saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07)); | ||
150 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
151 | msleep(SAA7146_I2C_DELAY); | ||
152 | |||
153 | /* clear all error-bits pending */ | ||
154 | saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); | ||
155 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
156 | msleep(SAA7146_I2C_DELAY); | ||
157 | |||
158 | /* the data sheet says it might be necessary to clear the status | ||
159 | twice after an abort */ | ||
160 | saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); | ||
161 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
162 | msleep(SAA7146_I2C_DELAY); | ||
163 | } | ||
164 | |||
165 | /* if any error is still present, a fatal error has occurred ... */ | ||
166 | status = saa7146_i2c_status(dev); | ||
167 | if ( dev->i2c_bitrate != status ) { | ||
168 | DEB_I2C("fatal error. status:0x%08x\n", status); | ||
169 | return -1; | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /* this functions writes out the data-byte 'dword' to the i2c-device. | ||
176 | it returns 0 if ok, -1 if the transfer failed, -2 if the transfer | ||
177 | failed badly (e.g. address error) */ | ||
178 | static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay) | ||
179 | { | ||
180 | u32 status = 0, mc2 = 0; | ||
181 | int trial = 0; | ||
182 | unsigned long timeout; | ||
183 | |||
184 | /* write out i2c-command */ | ||
185 | DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n", | ||
186 | *dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op); | ||
187 | |||
188 | if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { | ||
189 | |||
190 | saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); | ||
191 | saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword)); | ||
192 | |||
193 | dev->i2c_op = 1; | ||
194 | SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); | ||
195 | SAA7146_IER_ENABLE(dev, MASK_16|MASK_17); | ||
196 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
197 | |||
198 | timeout = HZ/100 + 1; /* 10ms */ | ||
199 | timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout); | ||
200 | if (timeout == -ERESTARTSYS || dev->i2c_op) { | ||
201 | SAA7146_IER_DISABLE(dev, MASK_16|MASK_17); | ||
202 | SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); | ||
203 | if (timeout == -ERESTARTSYS) | ||
204 | /* a signal arrived */ | ||
205 | return -ERESTARTSYS; | ||
206 | |||
207 | pr_warn("%s %s [irq]: timed out waiting for end of xfer\n", | ||
208 | dev->name, __func__); | ||
209 | return -EIO; | ||
210 | } | ||
211 | status = saa7146_read(dev, I2C_STATUS); | ||
212 | } else { | ||
213 | saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); | ||
214 | saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword)); | ||
215 | saa7146_write(dev, MC2, (MASK_00 | MASK_16)); | ||
216 | |||
217 | /* do not poll for i2c-status before upload is complete */ | ||
218 | timeout = jiffies + HZ/100 + 1; /* 10ms */ | ||
219 | while(1) { | ||
220 | mc2 = (saa7146_read(dev, MC2) & 0x1); | ||
221 | if( 0 != mc2 ) { | ||
222 | break; | ||
223 | } | ||
224 | if (time_after(jiffies,timeout)) { | ||
225 | pr_warn("%s %s: timed out waiting for MC2\n", | ||
226 | dev->name, __func__); | ||
227 | return -EIO; | ||
228 | } | ||
229 | } | ||
230 | /* wait until we get a transfer done or error */ | ||
231 | timeout = jiffies + HZ/100 + 1; /* 10ms */ | ||
232 | /* first read usually delivers bogus results... */ | ||
233 | saa7146_i2c_status(dev); | ||
234 | while(1) { | ||
235 | status = saa7146_i2c_status(dev); | ||
236 | if ((status & 0x3) != 1) | ||
237 | break; | ||
238 | if (time_after(jiffies,timeout)) { | ||
239 | /* this is normal when probing the bus | ||
240 | * (no answer from nonexisistant device...) | ||
241 | */ | ||
242 | pr_warn("%s %s [poll]: timed out waiting for end of xfer\n", | ||
243 | dev->name, __func__); | ||
244 | return -EIO; | ||
245 | } | ||
246 | if (++trial < 50 && short_delay) | ||
247 | udelay(10); | ||
248 | else | ||
249 | msleep(1); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /* give a detailed status report */ | ||
254 | if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR | | ||
255 | SAA7146_I2C_DTERR | SAA7146_I2C_DRERR | | ||
256 | SAA7146_I2C_AL | SAA7146_I2C_ERR | | ||
257 | SAA7146_I2C_BUSY)) ) { | ||
258 | |||
259 | if ( 0 == (status & SAA7146_I2C_ERR) || | ||
260 | 0 == (status & SAA7146_I2C_BUSY) ) { | ||
261 | /* it may take some time until ERR goes high - ignore */ | ||
262 | DEB_I2C("unexpected i2c status %04x\n", status); | ||
263 | } | ||
264 | if( 0 != (status & SAA7146_I2C_SPERR) ) { | ||
265 | DEB_I2C("error due to invalid start/stop condition\n"); | ||
266 | } | ||
267 | if( 0 != (status & SAA7146_I2C_DTERR) ) { | ||
268 | DEB_I2C("error in data transmission\n"); | ||
269 | } | ||
270 | if( 0 != (status & SAA7146_I2C_DRERR) ) { | ||
271 | DEB_I2C("error when receiving data\n"); | ||
272 | } | ||
273 | if( 0 != (status & SAA7146_I2C_AL) ) { | ||
274 | DEB_I2C("error because arbitration lost\n"); | ||
275 | } | ||
276 | |||
277 | /* we handle address-errors here */ | ||
278 | if( 0 != (status & SAA7146_I2C_APERR) ) { | ||
279 | DEB_I2C("error in address phase\n"); | ||
280 | return -EREMOTEIO; | ||
281 | } | ||
282 | |||
283 | return -EIO; | ||
284 | } | ||
285 | |||
286 | /* read back data, just in case we were reading ... */ | ||
287 | *dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER)); | ||
288 | |||
289 | DEB_I2C("after: 0x%08x\n", *dword); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries) | ||
294 | { | ||
295 | int i = 0, count = 0; | ||
296 | __le32 *buffer = dev->d_i2c.cpu_addr; | ||
297 | int err = 0; | ||
298 | int short_delay = 0; | ||
299 | |||
300 | if (mutex_lock_interruptible(&dev->i2c_lock)) | ||
301 | return -ERESTARTSYS; | ||
302 | |||
303 | for(i=0;i<num;i++) { | ||
304 | DEB_I2C("msg:%d/%d\n", i+1, num); | ||
305 | } | ||
306 | |||
307 | /* prepare the message(s), get number of u32s to transfer */ | ||
308 | count = saa7146_i2c_msg_prepare(msgs, num, buffer); | ||
309 | if ( 0 > count ) { | ||
310 | err = -1; | ||
311 | goto out; | ||
312 | } | ||
313 | |||
314 | if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) ) | ||
315 | short_delay = 1; | ||
316 | |||
317 | do { | ||
318 | /* reset the i2c-device if necessary */ | ||
319 | err = saa7146_i2c_reset(dev); | ||
320 | if ( 0 > err ) { | ||
321 | DEB_I2C("could not reset i2c-device\n"); | ||
322 | goto out; | ||
323 | } | ||
324 | |||
325 | /* write out the u32s one after another */ | ||
326 | for(i = 0; i < count; i++) { | ||
327 | err = saa7146_i2c_writeout(dev, &buffer[i], short_delay); | ||
328 | if ( 0 != err) { | ||
329 | /* this one is unsatisfying: some i2c slaves on some | ||
330 | dvb cards don't acknowledge correctly, so the saa7146 | ||
331 | thinks that an address error occurred. in that case, the | ||
332 | transaction should be retrying, even if an address error | ||
333 | occurred. analog saa7146 based cards extensively rely on | ||
334 | i2c address probing, however, and address errors indicate that a | ||
335 | device is really *not* there. retrying in that case | ||
336 | increases the time the device needs to probe greatly, so | ||
337 | it should be avoided. So we bail out in irq mode after an | ||
338 | address error and trust the saa7146 address error detection. */ | ||
339 | if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) | ||
340 | goto out; | ||
341 | DEB_I2C("error while sending message(s). starting again\n"); | ||
342 | break; | ||
343 | } | ||
344 | } | ||
345 | if( 0 == err ) { | ||
346 | err = num; | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | /* delay a bit before retrying */ | ||
351 | msleep(10); | ||
352 | |||
353 | } while (err != num && retries--); | ||
354 | |||
355 | /* quit if any error occurred */ | ||
356 | if (err != num) | ||
357 | goto out; | ||
358 | |||
359 | /* if any things had to be read, get the results */ | ||
360 | if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) { | ||
361 | DEB_I2C("could not cleanup i2c-message\n"); | ||
362 | err = -1; | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | /* return the number of delivered messages */ | ||
367 | DEB_I2C("transmission successful. (msg:%d)\n", err); | ||
368 | out: | ||
369 | /* another bug in revision 0: the i2c-registers get uploaded randomly by other | ||
370 | uploads, so we better clear them out before continuing */ | ||
371 | if( 0 == dev->revision ) { | ||
372 | __le32 zero = 0; | ||
373 | saa7146_i2c_reset(dev); | ||
374 | if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) { | ||
375 | pr_info("revision 0 error. this should never happen\n"); | ||
376 | } | ||
377 | } | ||
378 | |||
379 | mutex_unlock(&dev->i2c_lock); | ||
380 | return err; | ||
381 | } | ||
382 | |||
383 | /* utility functions */ | ||
384 | static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num) | ||
385 | { | ||
386 | struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); | ||
387 | struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev); | ||
388 | |||
389 | /* use helper function to transfer data */ | ||
390 | return saa7146_i2c_transfer(dev, msg, num, adapter->retries); | ||
391 | } | ||
392 | |||
393 | |||
394 | /*****************************************************************************/ | ||
395 | /* i2c-adapter helper functions */ | ||
396 | |||
397 | /* exported algorithm data */ | ||
398 | static struct i2c_algorithm saa7146_algo = { | ||
399 | .master_xfer = saa7146_i2c_xfer, | ||
400 | .functionality = saa7146_i2c_func, | ||
401 | }; | ||
402 | |||
403 | int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate) | ||
404 | { | ||
405 | DEB_EE("bitrate: 0x%08x\n", bitrate); | ||
406 | |||
407 | /* enable i2c-port pins */ | ||
408 | saa7146_write(dev, MC1, (MASK_08 | MASK_24)); | ||
409 | |||
410 | dev->i2c_bitrate = bitrate; | ||
411 | saa7146_i2c_reset(dev); | ||
412 | |||
413 | if (i2c_adapter) { | ||
414 | i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev); | ||
415 | i2c_adapter->dev.parent = &dev->pci->dev; | ||
416 | i2c_adapter->algo = &saa7146_algo; | ||
417 | i2c_adapter->algo_data = NULL; | ||
418 | i2c_adapter->timeout = SAA7146_I2C_TIMEOUT; | ||
419 | i2c_adapter->retries = SAA7146_I2C_RETRIES; | ||
420 | } | ||
421 | |||
422 | return 0; | ||
423 | } | ||
diff --git a/drivers/media/common/saa7146/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c deleted file mode 100644 index 1e71e374bbf..00000000000 --- a/drivers/media/common/saa7146/saa7146_vbi.c +++ /dev/null | |||
@@ -1,498 +0,0 @@ | |||
1 | #include <media/saa7146_vv.h> | ||
2 | |||
3 | static int vbi_pixel_to_capture = 720 * 2; | ||
4 | |||
5 | static int vbi_workaround(struct saa7146_dev *dev) | ||
6 | { | ||
7 | struct saa7146_vv *vv = dev->vv_data; | ||
8 | |||
9 | u32 *cpu; | ||
10 | dma_addr_t dma_addr; | ||
11 | |||
12 | int count = 0; | ||
13 | int i; | ||
14 | |||
15 | DECLARE_WAITQUEUE(wait, current); | ||
16 | |||
17 | DEB_VBI("dev:%p\n", dev); | ||
18 | |||
19 | /* once again, a bug in the saa7146: the brs acquisition | ||
20 | is buggy and especially the BXO-counter does not work | ||
21 | as specified. there is this workaround, but please | ||
22 | don't let me explain it. ;-) */ | ||
23 | |||
24 | cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr); | ||
25 | if (NULL == cpu) | ||
26 | return -ENOMEM; | ||
27 | |||
28 | /* setup some basic programming, just for the workaround */ | ||
29 | saa7146_write(dev, BASE_EVEN3, dma_addr); | ||
30 | saa7146_write(dev, BASE_ODD3, dma_addr+vbi_pixel_to_capture); | ||
31 | saa7146_write(dev, PROT_ADDR3, dma_addr+4096); | ||
32 | saa7146_write(dev, PITCH3, vbi_pixel_to_capture); | ||
33 | saa7146_write(dev, BASE_PAGE3, 0x0); | ||
34 | saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0)); | ||
35 | saa7146_write(dev, MC2, MASK_04|MASK_20); | ||
36 | |||
37 | /* load brs-control register */ | ||
38 | WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); | ||
39 | /* BXO = 1h, BRS to outbound */ | ||
40 | WRITE_RPS1(0xc000008c); | ||
41 | /* wait for vbi_a or vbi_b*/ | ||
42 | if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { | ||
43 | DEB_D("...using port b\n"); | ||
44 | WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B); | ||
45 | WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B); | ||
46 | /* | ||
47 | WRITE_RPS1(CMD_PAUSE | MASK_09); | ||
48 | */ | ||
49 | } else { | ||
50 | DEB_D("...using port a\n"); | ||
51 | WRITE_RPS1(CMD_PAUSE | MASK_10); | ||
52 | } | ||
53 | /* upload brs */ | ||
54 | WRITE_RPS1(CMD_UPLOAD | MASK_08); | ||
55 | /* load brs-control register */ | ||
56 | WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); | ||
57 | /* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */ | ||
58 | WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19); | ||
59 | /* wait for brs_done */ | ||
60 | WRITE_RPS1(CMD_PAUSE | MASK_08); | ||
61 | /* upload brs */ | ||
62 | WRITE_RPS1(CMD_UPLOAD | MASK_08); | ||
63 | /* load video-dma3 NumLines3 and NumBytes3 */ | ||
64 | WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4)); | ||
65 | /* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */ | ||
66 | WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture)); | ||
67 | /* load brs-control register */ | ||
68 | WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); | ||
69 | /* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */ | ||
70 | WRITE_RPS1((540 << 7) | (5 << 19)); // 5 == vbi_start | ||
71 | /* wait for brs_done */ | ||
72 | WRITE_RPS1(CMD_PAUSE | MASK_08); | ||
73 | /* upload brs and video-dma3*/ | ||
74 | WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04); | ||
75 | /* load mc2 register: enable dma3 */ | ||
76 | WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4)); | ||
77 | WRITE_RPS1(MASK_20 | MASK_04); | ||
78 | /* generate interrupt */ | ||
79 | WRITE_RPS1(CMD_INTERRUPT); | ||
80 | /* stop rps1 */ | ||
81 | WRITE_RPS1(CMD_STOP); | ||
82 | |||
83 | /* we have to do the workaround twice to be sure that | ||
84 | everything is ok */ | ||
85 | for(i = 0; i < 2; i++) { | ||
86 | |||
87 | /* indicate to the irq handler that we do the workaround */ | ||
88 | saa7146_write(dev, MC2, MASK_31|MASK_15); | ||
89 | |||
90 | saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0)); | ||
91 | saa7146_write(dev, MC2, MASK_04|MASK_20); | ||
92 | |||
93 | /* enable rps1 irqs */ | ||
94 | SAA7146_IER_ENABLE(dev,MASK_28); | ||
95 | |||
96 | /* prepare to wait to be woken up by the irq-handler */ | ||
97 | add_wait_queue(&vv->vbi_wq, &wait); | ||
98 | current->state = TASK_INTERRUPTIBLE; | ||
99 | |||
100 | /* start rps1 to enable workaround */ | ||
101 | saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); | ||
102 | saa7146_write(dev, MC1, (MASK_13 | MASK_29)); | ||
103 | |||
104 | schedule(); | ||
105 | |||
106 | DEB_VBI("brs bug workaround %d/1\n", i); | ||
107 | |||
108 | remove_wait_queue(&vv->vbi_wq, &wait); | ||
109 | current->state = TASK_RUNNING; | ||
110 | |||
111 | /* disable rps1 irqs */ | ||
112 | SAA7146_IER_DISABLE(dev,MASK_28); | ||
113 | |||
114 | /* stop video-dma3 */ | ||
115 | saa7146_write(dev, MC1, MASK_20); | ||
116 | |||
117 | if(signal_pending(current)) { | ||
118 | |||
119 | DEB_VBI("aborted (rps:0x%08x)\n", | ||
120 | saa7146_read(dev, RPS_ADDR1)); | ||
121 | |||
122 | /* stop rps1 for sure */ | ||
123 | saa7146_write(dev, MC1, MASK_29); | ||
124 | |||
125 | pci_free_consistent(dev->pci, 4096, cpu, dma_addr); | ||
126 | return -EINTR; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | pci_free_consistent(dev->pci, 4096, cpu, dma_addr); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) | ||
135 | { | ||
136 | struct saa7146_vv *vv = dev->vv_data; | ||
137 | |||
138 | struct saa7146_video_dma vdma3; | ||
139 | |||
140 | int count = 0; | ||
141 | unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; | ||
142 | unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; | ||
143 | |||
144 | /* | ||
145 | vdma3.base_even = 0xc8000000+2560*70; | ||
146 | vdma3.base_odd = 0xc8000000; | ||
147 | vdma3.prot_addr = 0xc8000000+2560*164; | ||
148 | vdma3.pitch = 2560; | ||
149 | vdma3.base_page = 0; | ||
150 | vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above! | ||
151 | */ | ||
152 | vdma3.base_even = buf->pt[2].offset; | ||
153 | vdma3.base_odd = buf->pt[2].offset + 16 * vbi_pixel_to_capture; | ||
154 | vdma3.prot_addr = buf->pt[2].offset + 16 * 2 * vbi_pixel_to_capture; | ||
155 | vdma3.pitch = vbi_pixel_to_capture; | ||
156 | vdma3.base_page = buf->pt[2].dma | ME1; | ||
157 | vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture; | ||
158 | |||
159 | saa7146_write_out_dma(dev, 3, &vdma3); | ||
160 | |||
161 | /* write beginning of rps-program */ | ||
162 | count = 0; | ||
163 | |||
164 | /* wait for o_fid_a/b / e_fid_a/b toggle only if bit 1 is not set */ | ||
165 | |||
166 | /* we don't wait here for the first field anymore. this is different from the video | ||
167 | capture and might cause that the first buffer is only half filled (with only | ||
168 | one field). but since this is some sort of streaming data, this is not that negative. | ||
169 | but by doing this, we can use the whole engine from videobuf-dma-sg.c... */ | ||
170 | |||
171 | /* | ||
172 | WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait); | ||
173 | WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait); | ||
174 | */ | ||
175 | /* set bit 1 */ | ||
176 | WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4)); | ||
177 | WRITE_RPS1(MASK_28 | MASK_12); | ||
178 | |||
179 | /* turn on video-dma3 */ | ||
180 | WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4)); | ||
181 | WRITE_RPS1(MASK_04 | MASK_20); /* => mask */ | ||
182 | WRITE_RPS1(MASK_04 | MASK_20); /* => values */ | ||
183 | |||
184 | /* wait for o_fid_a/b / e_fid_a/b toggle */ | ||
185 | WRITE_RPS1(CMD_PAUSE | o_wait); | ||
186 | WRITE_RPS1(CMD_PAUSE | e_wait); | ||
187 | |||
188 | /* generate interrupt */ | ||
189 | WRITE_RPS1(CMD_INTERRUPT); | ||
190 | |||
191 | /* stop */ | ||
192 | WRITE_RPS1(CMD_STOP); | ||
193 | |||
194 | /* enable rps1 irqs */ | ||
195 | SAA7146_IER_ENABLE(dev, MASK_28); | ||
196 | |||
197 | /* write the address of the rps-program */ | ||
198 | saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); | ||
199 | |||
200 | /* turn on rps */ | ||
201 | saa7146_write(dev, MC1, (MASK_13 | MASK_29)); | ||
202 | } | ||
203 | |||
204 | static int buffer_activate(struct saa7146_dev *dev, | ||
205 | struct saa7146_buf *buf, | ||
206 | struct saa7146_buf *next) | ||
207 | { | ||
208 | struct saa7146_vv *vv = dev->vv_data; | ||
209 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
210 | |||
211 | DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next); | ||
212 | saa7146_set_vbi_capture(dev,buf,next); | ||
213 | |||
214 | mod_timer(&vv->vbi_dmaq.timeout, jiffies+BUFFER_TIMEOUT); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field) | ||
219 | { | ||
220 | struct file *file = q->priv_data; | ||
221 | struct saa7146_fh *fh = file->private_data; | ||
222 | struct saa7146_dev *dev = fh->dev; | ||
223 | struct saa7146_buf *buf = (struct saa7146_buf *)vb; | ||
224 | |||
225 | int err = 0; | ||
226 | int lines, llength, size; | ||
227 | |||
228 | lines = 16 * 2 ; /* 2 fields */ | ||
229 | llength = vbi_pixel_to_capture; | ||
230 | size = lines * llength; | ||
231 | |||
232 | DEB_VBI("vb:%p\n", vb); | ||
233 | |||
234 | if (0 != buf->vb.baddr && buf->vb.bsize < size) { | ||
235 | DEB_VBI("size mismatch\n"); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
239 | if (buf->vb.size != size) | ||
240 | saa7146_dma_free(dev,q,buf); | ||
241 | |||
242 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
243 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
244 | |||
245 | buf->vb.width = llength; | ||
246 | buf->vb.height = lines; | ||
247 | buf->vb.size = size; | ||
248 | buf->vb.field = field; // FIXME: check this | ||
249 | |||
250 | saa7146_pgtable_free(dev->pci, &buf->pt[2]); | ||
251 | saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); | ||
252 | |||
253 | err = videobuf_iolock(q,&buf->vb, NULL); | ||
254 | if (err) | ||
255 | goto oops; | ||
256 | err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], | ||
257 | dma->sglist, dma->sglen); | ||
258 | if (0 != err) | ||
259 | return err; | ||
260 | } | ||
261 | buf->vb.state = VIDEOBUF_PREPARED; | ||
262 | buf->activate = buffer_activate; | ||
263 | |||
264 | return 0; | ||
265 | |||
266 | oops: | ||
267 | DEB_VBI("error out\n"); | ||
268 | saa7146_dma_free(dev,q,buf); | ||
269 | |||
270 | return err; | ||
271 | } | ||
272 | |||
273 | static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | ||
274 | { | ||
275 | int llength,lines; | ||
276 | |||
277 | lines = 16 * 2 ; /* 2 fields */ | ||
278 | llength = vbi_pixel_to_capture; | ||
279 | |||
280 | *size = lines * llength; | ||
281 | *count = 2; | ||
282 | |||
283 | DEB_VBI("count:%d, size:%d\n", *count, *size); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
289 | { | ||
290 | struct file *file = q->priv_data; | ||
291 | struct saa7146_fh *fh = file->private_data; | ||
292 | struct saa7146_dev *dev = fh->dev; | ||
293 | struct saa7146_vv *vv = dev->vv_data; | ||
294 | struct saa7146_buf *buf = (struct saa7146_buf *)vb; | ||
295 | |||
296 | DEB_VBI("vb:%p\n", vb); | ||
297 | saa7146_buffer_queue(dev, &vv->vbi_dmaq, buf); | ||
298 | } | ||
299 | |||
300 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
301 | { | ||
302 | struct file *file = q->priv_data; | ||
303 | struct saa7146_fh *fh = file->private_data; | ||
304 | struct saa7146_dev *dev = fh->dev; | ||
305 | struct saa7146_buf *buf = (struct saa7146_buf *)vb; | ||
306 | |||
307 | DEB_VBI("vb:%p\n", vb); | ||
308 | saa7146_dma_free(dev,q,buf); | ||
309 | } | ||
310 | |||
311 | static struct videobuf_queue_ops vbi_qops = { | ||
312 | .buf_setup = buffer_setup, | ||
313 | .buf_prepare = buffer_prepare, | ||
314 | .buf_queue = buffer_queue, | ||
315 | .buf_release = buffer_release, | ||
316 | }; | ||
317 | |||
318 | /* ------------------------------------------------------------------ */ | ||
319 | |||
320 | static void vbi_stop(struct saa7146_fh *fh, struct file *file) | ||
321 | { | ||
322 | struct saa7146_dev *dev = fh->dev; | ||
323 | struct saa7146_vv *vv = dev->vv_data; | ||
324 | unsigned long flags; | ||
325 | DEB_VBI("dev:%p, fh:%p\n", dev, fh); | ||
326 | |||
327 | spin_lock_irqsave(&dev->slock,flags); | ||
328 | |||
329 | /* disable rps1 */ | ||
330 | saa7146_write(dev, MC1, MASK_29); | ||
331 | |||
332 | /* disable rps1 irqs */ | ||
333 | SAA7146_IER_DISABLE(dev, MASK_28); | ||
334 | |||
335 | /* shut down dma 3 transfers */ | ||
336 | saa7146_write(dev, MC1, MASK_20); | ||
337 | |||
338 | if (vv->vbi_dmaq.curr) | ||
339 | saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE); | ||
340 | |||
341 | videobuf_queue_cancel(&fh->vbi_q); | ||
342 | |||
343 | vv->vbi_streaming = NULL; | ||
344 | |||
345 | del_timer(&vv->vbi_dmaq.timeout); | ||
346 | del_timer(&vv->vbi_read_timeout); | ||
347 | |||
348 | spin_unlock_irqrestore(&dev->slock, flags); | ||
349 | } | ||
350 | |||
351 | static void vbi_read_timeout(unsigned long data) | ||
352 | { | ||
353 | struct file *file = (struct file*)data; | ||
354 | struct saa7146_fh *fh = file->private_data; | ||
355 | struct saa7146_dev *dev = fh->dev; | ||
356 | |||
357 | DEB_VBI("dev:%p, fh:%p\n", dev, fh); | ||
358 | |||
359 | vbi_stop(fh, file); | ||
360 | } | ||
361 | |||
362 | static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv) | ||
363 | { | ||
364 | DEB_VBI("dev:%p\n", dev); | ||
365 | |||
366 | INIT_LIST_HEAD(&vv->vbi_dmaq.queue); | ||
367 | |||
368 | init_timer(&vv->vbi_dmaq.timeout); | ||
369 | vv->vbi_dmaq.timeout.function = saa7146_buffer_timeout; | ||
370 | vv->vbi_dmaq.timeout.data = (unsigned long)(&vv->vbi_dmaq); | ||
371 | vv->vbi_dmaq.dev = dev; | ||
372 | |||
373 | init_waitqueue_head(&vv->vbi_wq); | ||
374 | } | ||
375 | |||
376 | static int vbi_open(struct saa7146_dev *dev, struct file *file) | ||
377 | { | ||
378 | struct saa7146_fh *fh = file->private_data; | ||
379 | struct saa7146_vv *vv = fh->dev->vv_data; | ||
380 | |||
381 | u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1); | ||
382 | int ret = 0; | ||
383 | |||
384 | DEB_VBI("dev:%p, fh:%p\n", dev, fh); | ||
385 | |||
386 | ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS); | ||
387 | if (0 == ret) { | ||
388 | DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n"); | ||
389 | return -EBUSY; | ||
390 | } | ||
391 | |||
392 | /* adjust arbitrition control for video dma 3 */ | ||
393 | arbtr_ctrl &= ~0x1f0000; | ||
394 | arbtr_ctrl |= 0x1d0000; | ||
395 | saa7146_write(dev, PCI_BT_V1, arbtr_ctrl); | ||
396 | saa7146_write(dev, MC2, (MASK_04|MASK_20)); | ||
397 | |||
398 | videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops, | ||
399 | &dev->pci->dev, &dev->slock, | ||
400 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
401 | V4L2_FIELD_SEQ_TB, // FIXME: does this really work? | ||
402 | sizeof(struct saa7146_buf), | ||
403 | file, &dev->v4l2_lock); | ||
404 | |||
405 | vv->vbi_read_timeout.function = vbi_read_timeout; | ||
406 | vv->vbi_read_timeout.data = (unsigned long)file; | ||
407 | |||
408 | /* initialize the brs */ | ||
409 | if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) { | ||
410 | saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19)); | ||
411 | } else { | ||
412 | saa7146_write(dev, BRS_CTRL, 0x00000001); | ||
413 | |||
414 | if (0 != (ret = vbi_workaround(dev))) { | ||
415 | DEB_VBI("vbi workaround failed!\n"); | ||
416 | /* return ret;*/ | ||
417 | } | ||
418 | } | ||
419 | |||
420 | /* upload brs register */ | ||
421 | saa7146_write(dev, MC2, (MASK_08|MASK_24)); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static void vbi_close(struct saa7146_dev *dev, struct file *file) | ||
426 | { | ||
427 | struct saa7146_fh *fh = file->private_data; | ||
428 | struct saa7146_vv *vv = dev->vv_data; | ||
429 | DEB_VBI("dev:%p, fh:%p\n", dev, fh); | ||
430 | |||
431 | if( fh == vv->vbi_streaming ) { | ||
432 | vbi_stop(fh, file); | ||
433 | } | ||
434 | saa7146_res_free(fh, RESOURCE_DMA3_BRS); | ||
435 | } | ||
436 | |||
437 | static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status) | ||
438 | { | ||
439 | struct saa7146_vv *vv = dev->vv_data; | ||
440 | spin_lock(&dev->slock); | ||
441 | |||
442 | if (vv->vbi_dmaq.curr) { | ||
443 | DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_dmaq.curr); | ||
444 | /* this must be += 2, one count for each field */ | ||
445 | vv->vbi_fieldcount+=2; | ||
446 | vv->vbi_dmaq.curr->vb.field_count = vv->vbi_fieldcount; | ||
447 | saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE); | ||
448 | } else { | ||
449 | DEB_VBI("dev:%p\n", dev); | ||
450 | } | ||
451 | saa7146_buffer_next(dev, &vv->vbi_dmaq, 1); | ||
452 | |||
453 | spin_unlock(&dev->slock); | ||
454 | } | ||
455 | |||
456 | static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
457 | { | ||
458 | struct saa7146_fh *fh = file->private_data; | ||
459 | struct saa7146_dev *dev = fh->dev; | ||
460 | struct saa7146_vv *vv = dev->vv_data; | ||
461 | ssize_t ret = 0; | ||
462 | |||
463 | DEB_VBI("dev:%p, fh:%p\n", dev, fh); | ||
464 | |||
465 | if( NULL == vv->vbi_streaming ) { | ||
466 | // fixme: check if dma3 is available | ||
467 | // fixme: activate vbi engine here if necessary. (really?) | ||
468 | vv->vbi_streaming = fh; | ||
469 | } | ||
470 | |||
471 | if( fh != vv->vbi_streaming ) { | ||
472 | DEB_VBI("open %p is already using vbi capture\n", | ||
473 | vv->vbi_streaming); | ||
474 | return -EBUSY; | ||
475 | } | ||
476 | |||
477 | mod_timer(&vv->vbi_read_timeout, jiffies+BUFFER_TIMEOUT); | ||
478 | ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1, | ||
479 | file->f_flags & O_NONBLOCK); | ||
480 | /* | ||
481 | printk("BASE_ODD3: 0x%08x\n", saa7146_read(dev, BASE_ODD3)); | ||
482 | printk("BASE_EVEN3: 0x%08x\n", saa7146_read(dev, BASE_EVEN3)); | ||
483 | printk("PROT_ADDR3: 0x%08x\n", saa7146_read(dev, PROT_ADDR3)); | ||
484 | printk("PITCH3: 0x%08x\n", saa7146_read(dev, PITCH3)); | ||
485 | printk("BASE_PAGE3: 0x%08x\n", saa7146_read(dev, BASE_PAGE3)); | ||
486 | printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3)); | ||
487 | printk("BRS_CTRL: 0x%08x\n", saa7146_read(dev, BRS_CTRL)); | ||
488 | */ | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | struct saa7146_use_ops saa7146_vbi_uops = { | ||
493 | .init = vbi_init, | ||
494 | .open = vbi_open, | ||
495 | .release = vbi_close, | ||
496 | .irq_done = vbi_irq_done, | ||
497 | .read = vbi_read, | ||
498 | }; | ||
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c deleted file mode 100644 index 4143d61f79b..00000000000 --- a/drivers/media/common/saa7146/saa7146_video.c +++ /dev/null | |||
@@ -1,1332 +0,0 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
3 | #include <media/saa7146_vv.h> | ||
4 | #include <media/v4l2-chip-ident.h> | ||
5 | #include <media/v4l2-event.h> | ||
6 | #include <media/v4l2-ctrls.h> | ||
7 | #include <linux/module.h> | ||
8 | |||
9 | static int max_memory = 32; | ||
10 | |||
11 | module_param(max_memory, int, 0644); | ||
12 | MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)"); | ||
13 | |||
14 | #define IS_CAPTURE_ACTIVE(fh) \ | ||
15 | (((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh)) | ||
16 | |||
17 | #define IS_OVERLAY_ACTIVE(fh) \ | ||
18 | (((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh)) | ||
19 | |||
20 | /* format descriptions for capture and preview */ | ||
21 | static struct saa7146_format formats[] = { | ||
22 | { | ||
23 | .name = "RGB-8 (3-3-2)", | ||
24 | .pixelformat = V4L2_PIX_FMT_RGB332, | ||
25 | .trans = RGB08_COMPOSED, | ||
26 | .depth = 8, | ||
27 | .flags = 0, | ||
28 | }, { | ||
29 | .name = "RGB-16 (5/B-6/G-5/R)", | ||
30 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
31 | .trans = RGB16_COMPOSED, | ||
32 | .depth = 16, | ||
33 | .flags = 0, | ||
34 | }, { | ||
35 | .name = "RGB-24 (B-G-R)", | ||
36 | .pixelformat = V4L2_PIX_FMT_BGR24, | ||
37 | .trans = RGB24_COMPOSED, | ||
38 | .depth = 24, | ||
39 | .flags = 0, | ||
40 | }, { | ||
41 | .name = "RGB-32 (B-G-R)", | ||
42 | .pixelformat = V4L2_PIX_FMT_BGR32, | ||
43 | .trans = RGB32_COMPOSED, | ||
44 | .depth = 32, | ||
45 | .flags = 0, | ||
46 | }, { | ||
47 | .name = "RGB-32 (R-G-B)", | ||
48 | .pixelformat = V4L2_PIX_FMT_RGB32, | ||
49 | .trans = RGB32_COMPOSED, | ||
50 | .depth = 32, | ||
51 | .flags = 0, | ||
52 | .swap = 0x2, | ||
53 | }, { | ||
54 | .name = "Greyscale-8", | ||
55 | .pixelformat = V4L2_PIX_FMT_GREY, | ||
56 | .trans = Y8, | ||
57 | .depth = 8, | ||
58 | .flags = 0, | ||
59 | }, { | ||
60 | .name = "YUV 4:2:2 planar (Y-Cb-Cr)", | ||
61 | .pixelformat = V4L2_PIX_FMT_YUV422P, | ||
62 | .trans = YUV422_DECOMPOSED, | ||
63 | .depth = 16, | ||
64 | .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR, | ||
65 | }, { | ||
66 | .name = "YVU 4:2:0 planar (Y-Cb-Cr)", | ||
67 | .pixelformat = V4L2_PIX_FMT_YVU420, | ||
68 | .trans = YUV420_DECOMPOSED, | ||
69 | .depth = 12, | ||
70 | .flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR, | ||
71 | }, { | ||
72 | .name = "YUV 4:2:0 planar (Y-Cb-Cr)", | ||
73 | .pixelformat = V4L2_PIX_FMT_YUV420, | ||
74 | .trans = YUV420_DECOMPOSED, | ||
75 | .depth = 12, | ||
76 | .flags = FORMAT_IS_PLANAR, | ||
77 | }, { | ||
78 | .name = "YUV 4:2:2 (U-Y-V-Y)", | ||
79 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
80 | .trans = YUV422_COMPOSED, | ||
81 | .depth = 16, | ||
82 | .flags = 0, | ||
83 | } | ||
84 | }; | ||
85 | |||
86 | /* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps. | ||
87 | due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped | ||
88 | (like V4L2_PIX_FMT_YUYV) ... 8-( */ | ||
89 | |||
90 | static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); | ||
91 | |||
92 | struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc) | ||
93 | { | ||
94 | int i, j = NUM_FORMATS; | ||
95 | |||
96 | for (i = 0; i < j; i++) { | ||
97 | if (formats[i].pixelformat == fourcc) { | ||
98 | return formats+i; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc); | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
106 | static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f); | ||
107 | |||
108 | int saa7146_start_preview(struct saa7146_fh *fh) | ||
109 | { | ||
110 | struct saa7146_dev *dev = fh->dev; | ||
111 | struct saa7146_vv *vv = dev->vv_data; | ||
112 | struct v4l2_format fmt; | ||
113 | int ret = 0, err = 0; | ||
114 | |||
115 | DEB_EE("dev:%p, fh:%p\n", dev, fh); | ||
116 | |||
117 | /* check if we have overlay information */ | ||
118 | if (vv->ov.fh == NULL) { | ||
119 | DEB_D("no overlay data available. try S_FMT first.\n"); | ||
120 | return -EAGAIN; | ||
121 | } | ||
122 | |||
123 | /* check if streaming capture is running */ | ||
124 | if (IS_CAPTURE_ACTIVE(fh) != 0) { | ||
125 | DEB_D("streaming capture is active\n"); | ||
126 | return -EBUSY; | ||
127 | } | ||
128 | |||
129 | /* check if overlay is running */ | ||
130 | if (IS_OVERLAY_ACTIVE(fh) != 0) { | ||
131 | if (vv->video_fh == fh) { | ||
132 | DEB_D("overlay is already active\n"); | ||
133 | return 0; | ||
134 | } | ||
135 | DEB_D("overlay is already active in another open\n"); | ||
136 | return -EBUSY; | ||
137 | } | ||
138 | |||
139 | if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) { | ||
140 | DEB_D("cannot get necessary overlay resources\n"); | ||
141 | return -EBUSY; | ||
142 | } | ||
143 | |||
144 | fmt.fmt.win = vv->ov.win; | ||
145 | err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt); | ||
146 | if (0 != err) { | ||
147 | saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); | ||
148 | return -EBUSY; | ||
149 | } | ||
150 | vv->ov.win = fmt.fmt.win; | ||
151 | |||
152 | DEB_D("%dx%d+%d+%d %s field=%s\n", | ||
153 | vv->ov.win.w.width, vv->ov.win.w.height, | ||
154 | vv->ov.win.w.left, vv->ov.win.w.top, | ||
155 | vv->ov_fmt->name, v4l2_field_names[vv->ov.win.field]); | ||
156 | |||
157 | if (0 != (ret = saa7146_enable_overlay(fh))) { | ||
158 | DEB_D("enabling overlay failed: %d\n", ret); | ||
159 | saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | vv->video_status = STATUS_OVERLAY; | ||
164 | vv->video_fh = fh; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | EXPORT_SYMBOL_GPL(saa7146_start_preview); | ||
169 | |||
170 | int saa7146_stop_preview(struct saa7146_fh *fh) | ||
171 | { | ||
172 | struct saa7146_dev *dev = fh->dev; | ||
173 | struct saa7146_vv *vv = dev->vv_data; | ||
174 | |||
175 | DEB_EE("dev:%p, fh:%p\n", dev, fh); | ||
176 | |||
177 | /* check if streaming capture is running */ | ||
178 | if (IS_CAPTURE_ACTIVE(fh) != 0) { | ||
179 | DEB_D("streaming capture is active\n"); | ||
180 | return -EBUSY; | ||
181 | } | ||
182 | |||
183 | /* check if overlay is running at all */ | ||
184 | if ((vv->video_status & STATUS_OVERLAY) == 0) { | ||
185 | DEB_D("no active overlay\n"); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | if (vv->video_fh != fh) { | ||
190 | DEB_D("overlay is active, but in another open\n"); | ||
191 | return -EBUSY; | ||
192 | } | ||
193 | |||
194 | vv->video_status = 0; | ||
195 | vv->video_fh = NULL; | ||
196 | |||
197 | saa7146_disable_overlay(fh); | ||
198 | |||
199 | saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | EXPORT_SYMBOL_GPL(saa7146_stop_preview); | ||
204 | |||
205 | /********************************************************************************/ | ||
206 | /* common pagetable functions */ | ||
207 | |||
208 | static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) | ||
209 | { | ||
210 | struct pci_dev *pci = dev->pci; | ||
211 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
212 | struct scatterlist *list = dma->sglist; | ||
213 | int length = dma->sglen; | ||
214 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); | ||
215 | |||
216 | DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length); | ||
217 | |||
218 | if( 0 != IS_PLANAR(sfmt->trans)) { | ||
219 | struct saa7146_pgtable *pt1 = &buf->pt[0]; | ||
220 | struct saa7146_pgtable *pt2 = &buf->pt[1]; | ||
221 | struct saa7146_pgtable *pt3 = &buf->pt[2]; | ||
222 | __le32 *ptr1, *ptr2, *ptr3; | ||
223 | __le32 fill; | ||
224 | |||
225 | int size = buf->fmt->width*buf->fmt->height; | ||
226 | int i,p,m1,m2,m3,o1,o2; | ||
227 | |||
228 | switch( sfmt->depth ) { | ||
229 | case 12: { | ||
230 | /* create some offsets inside the page table */ | ||
231 | m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1; | ||
232 | m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1; | ||
233 | m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; | ||
234 | o1 = size%PAGE_SIZE; | ||
235 | o2 = (size+(size/4))%PAGE_SIZE; | ||
236 | DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n", | ||
237 | size, m1, m2, m3, o1, o2); | ||
238 | break; | ||
239 | } | ||
240 | case 16: { | ||
241 | /* create some offsets inside the page table */ | ||
242 | m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1; | ||
243 | m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; | ||
244 | m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1; | ||
245 | o1 = size%PAGE_SIZE; | ||
246 | o2 = (size+(size/2))%PAGE_SIZE; | ||
247 | DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n", | ||
248 | size, m1, m2, m3, o1, o2); | ||
249 | break; | ||
250 | } | ||
251 | default: { | ||
252 | return -1; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | ptr1 = pt1->cpu; | ||
257 | ptr2 = pt2->cpu; | ||
258 | ptr3 = pt3->cpu; | ||
259 | |||
260 | /* walk all pages, copy all page addresses to ptr1 */ | ||
261 | for (i = 0; i < length; i++, list++) { | ||
262 | for (p = 0; p * 4096 < list->length; p++, ptr1++) { | ||
263 | *ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset); | ||
264 | } | ||
265 | } | ||
266 | /* | ||
267 | ptr1 = pt1->cpu; | ||
268 | for(j=0;j<40;j++) { | ||
269 | printk("ptr1 %d: 0x%08x\n",j,ptr1[j]); | ||
270 | } | ||
271 | */ | ||
272 | |||
273 | /* if we have a user buffer, the first page may not be | ||
274 | aligned to a page boundary. */ | ||
275 | pt1->offset = dma->sglist->offset; | ||
276 | pt2->offset = pt1->offset+o1; | ||
277 | pt3->offset = pt1->offset+o2; | ||
278 | |||
279 | /* create video-dma2 page table */ | ||
280 | ptr1 = pt1->cpu; | ||
281 | for(i = m1; i <= m2 ; i++, ptr2++) { | ||
282 | *ptr2 = ptr1[i]; | ||
283 | } | ||
284 | fill = *(ptr2-1); | ||
285 | for(;i<1024;i++,ptr2++) { | ||
286 | *ptr2 = fill; | ||
287 | } | ||
288 | /* create video-dma3 page table */ | ||
289 | ptr1 = pt1->cpu; | ||
290 | for(i = m2; i <= m3; i++,ptr3++) { | ||
291 | *ptr3 = ptr1[i]; | ||
292 | } | ||
293 | fill = *(ptr3-1); | ||
294 | for(;i<1024;i++,ptr3++) { | ||
295 | *ptr3 = fill; | ||
296 | } | ||
297 | /* finally: finish up video-dma1 page table */ | ||
298 | ptr1 = pt1->cpu+m1; | ||
299 | fill = pt1->cpu[m1]; | ||
300 | for(i=m1;i<1024;i++,ptr1++) { | ||
301 | *ptr1 = fill; | ||
302 | } | ||
303 | /* | ||
304 | ptr1 = pt1->cpu; | ||
305 | ptr2 = pt2->cpu; | ||
306 | ptr3 = pt3->cpu; | ||
307 | for(j=0;j<40;j++) { | ||
308 | printk("ptr1 %d: 0x%08x\n",j,ptr1[j]); | ||
309 | } | ||
310 | for(j=0;j<40;j++) { | ||
311 | printk("ptr2 %d: 0x%08x\n",j,ptr2[j]); | ||
312 | } | ||
313 | for(j=0;j<40;j++) { | ||
314 | printk("ptr3 %d: 0x%08x\n",j,ptr3[j]); | ||
315 | } | ||
316 | */ | ||
317 | } else { | ||
318 | struct saa7146_pgtable *pt = &buf->pt[0]; | ||
319 | return saa7146_pgtable_build_single(pci, pt, list, length); | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | |||
326 | /********************************************************************************/ | ||
327 | /* file operations */ | ||
328 | |||
329 | static int video_begin(struct saa7146_fh *fh) | ||
330 | { | ||
331 | struct saa7146_dev *dev = fh->dev; | ||
332 | struct saa7146_vv *vv = dev->vv_data; | ||
333 | struct saa7146_format *fmt = NULL; | ||
334 | unsigned int resource; | ||
335 | int ret = 0, err = 0; | ||
336 | |||
337 | DEB_EE("dev:%p, fh:%p\n", dev, fh); | ||
338 | |||
339 | if ((vv->video_status & STATUS_CAPTURE) != 0) { | ||
340 | if (vv->video_fh == fh) { | ||
341 | DEB_S("already capturing\n"); | ||
342 | return 0; | ||
343 | } | ||
344 | DEB_S("already capturing in another open\n"); | ||
345 | return -EBUSY; | ||
346 | } | ||
347 | |||
348 | if ((vv->video_status & STATUS_OVERLAY) != 0) { | ||
349 | DEB_S("warning: suspending overlay video for streaming capture\n"); | ||
350 | vv->ov_suspend = vv->video_fh; | ||
351 | err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ | ||
352 | if (0 != err) { | ||
353 | DEB_D("suspending video failed. aborting\n"); | ||
354 | return err; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat); | ||
359 | /* we need to have a valid format set here */ | ||
360 | BUG_ON(NULL == fmt); | ||
361 | |||
362 | if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { | ||
363 | resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS; | ||
364 | } else { | ||
365 | resource = RESOURCE_DMA1_HPS; | ||
366 | } | ||
367 | |||
368 | ret = saa7146_res_get(fh, resource); | ||
369 | if (0 == ret) { | ||
370 | DEB_S("cannot get capture resource %d\n", resource); | ||
371 | if (vv->ov_suspend != NULL) { | ||
372 | saa7146_start_preview(vv->ov_suspend); | ||
373 | vv->ov_suspend = NULL; | ||
374 | } | ||
375 | return -EBUSY; | ||
376 | } | ||
377 | |||
378 | /* clear out beginning of streaming bit (rps register 0)*/ | ||
379 | saa7146_write(dev, MC2, MASK_27 ); | ||
380 | |||
381 | /* enable rps0 irqs */ | ||
382 | SAA7146_IER_ENABLE(dev, MASK_27); | ||
383 | |||
384 | vv->video_fh = fh; | ||
385 | vv->video_status = STATUS_CAPTURE; | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int video_end(struct saa7146_fh *fh, struct file *file) | ||
391 | { | ||
392 | struct saa7146_dev *dev = fh->dev; | ||
393 | struct saa7146_vv *vv = dev->vv_data; | ||
394 | struct saa7146_format *fmt = NULL; | ||
395 | unsigned long flags; | ||
396 | unsigned int resource; | ||
397 | u32 dmas = 0; | ||
398 | DEB_EE("dev:%p, fh:%p\n", dev, fh); | ||
399 | |||
400 | if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { | ||
401 | DEB_S("not capturing\n"); | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | if (vv->video_fh != fh) { | ||
406 | DEB_S("capturing, but in another open\n"); | ||
407 | return -EBUSY; | ||
408 | } | ||
409 | |||
410 | fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat); | ||
411 | /* we need to have a valid format set here */ | ||
412 | BUG_ON(NULL == fmt); | ||
413 | |||
414 | if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { | ||
415 | resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS; | ||
416 | dmas = MASK_22 | MASK_21 | MASK_20; | ||
417 | } else { | ||
418 | resource = RESOURCE_DMA1_HPS; | ||
419 | dmas = MASK_22; | ||
420 | } | ||
421 | spin_lock_irqsave(&dev->slock,flags); | ||
422 | |||
423 | /* disable rps0 */ | ||
424 | saa7146_write(dev, MC1, MASK_28); | ||
425 | |||
426 | /* disable rps0 irqs */ | ||
427 | SAA7146_IER_DISABLE(dev, MASK_27); | ||
428 | |||
429 | /* shut down all used video dma transfers */ | ||
430 | saa7146_write(dev, MC1, dmas); | ||
431 | |||
432 | spin_unlock_irqrestore(&dev->slock, flags); | ||
433 | |||
434 | vv->video_fh = NULL; | ||
435 | vv->video_status = 0; | ||
436 | |||
437 | saa7146_res_free(fh, resource); | ||
438 | |||
439 | if (vv->ov_suspend != NULL) { | ||
440 | saa7146_start_preview(vv->ov_suspend); | ||
441 | vv->ov_suspend = NULL; | ||
442 | } | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) | ||
448 | { | ||
449 | struct video_device *vdev = video_devdata(file); | ||
450 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
451 | |||
452 | strcpy((char *)cap->driver, "saa7146 v4l2"); | ||
453 | strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); | ||
454 | sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); | ||
455 | cap->device_caps = | ||
456 | V4L2_CAP_VIDEO_CAPTURE | | ||
457 | V4L2_CAP_VIDEO_OVERLAY | | ||
458 | V4L2_CAP_READWRITE | | ||
459 | V4L2_CAP_STREAMING; | ||
460 | cap->device_caps |= dev->ext_vv_data->capabilities; | ||
461 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
462 | if (vdev->vfl_type == VFL_TYPE_GRABBER) | ||
463 | cap->device_caps &= | ||
464 | ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT); | ||
465 | else | ||
466 | cap->device_caps &= | ||
467 | ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO); | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | ||
472 | { | ||
473 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
474 | struct saa7146_vv *vv = dev->vv_data; | ||
475 | |||
476 | *fb = vv->ov_fb; | ||
477 | fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; | ||
478 | fb->flags = V4L2_FBUF_FLAG_PRIMARY; | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb) | ||
483 | { | ||
484 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
485 | struct saa7146_vv *vv = dev->vv_data; | ||
486 | struct saa7146_format *fmt; | ||
487 | |||
488 | DEB_EE("VIDIOC_S_FBUF\n"); | ||
489 | |||
490 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) | ||
491 | return -EPERM; | ||
492 | |||
493 | /* check args */ | ||
494 | fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat); | ||
495 | if (NULL == fmt) | ||
496 | return -EINVAL; | ||
497 | |||
498 | /* planar formats are not allowed for overlay video, clipping and video dma would clash */ | ||
499 | if (fmt->flags & FORMAT_IS_PLANAR) | ||
500 | DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n", | ||
501 | (char *)&fmt->pixelformat); | ||
502 | |||
503 | /* check if overlay is running */ | ||
504 | if (IS_OVERLAY_ACTIVE(fh) != 0) { | ||
505 | if (vv->video_fh != fh) { | ||
506 | DEB_D("refusing to change framebuffer informations while overlay is active in another open\n"); | ||
507 | return -EBUSY; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | /* ok, accept it */ | ||
512 | vv->ov_fb = *fb; | ||
513 | vv->ov_fmt = fmt; | ||
514 | |||
515 | if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) { | ||
516 | vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; | ||
517 | DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline); | ||
518 | } | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) | ||
523 | { | ||
524 | if (f->index >= NUM_FORMATS) | ||
525 | return -EINVAL; | ||
526 | strlcpy((char *)f->description, formats[f->index].name, | ||
527 | sizeof(f->description)); | ||
528 | f->pixelformat = formats[f->index].pixelformat; | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | int saa7146_s_ctrl(struct v4l2_ctrl *ctrl) | ||
533 | { | ||
534 | struct saa7146_dev *dev = container_of(ctrl->handler, | ||
535 | struct saa7146_dev, ctrl_handler); | ||
536 | struct saa7146_vv *vv = dev->vv_data; | ||
537 | u32 val; | ||
538 | |||
539 | switch (ctrl->id) { | ||
540 | case V4L2_CID_BRIGHTNESS: | ||
541 | val = saa7146_read(dev, BCS_CTRL); | ||
542 | val &= 0x00ffffff; | ||
543 | val |= (ctrl->val << 24); | ||
544 | saa7146_write(dev, BCS_CTRL, val); | ||
545 | saa7146_write(dev, MC2, MASK_22 | MASK_06); | ||
546 | break; | ||
547 | |||
548 | case V4L2_CID_CONTRAST: | ||
549 | val = saa7146_read(dev, BCS_CTRL); | ||
550 | val &= 0xff00ffff; | ||
551 | val |= (ctrl->val << 16); | ||
552 | saa7146_write(dev, BCS_CTRL, val); | ||
553 | saa7146_write(dev, MC2, MASK_22 | MASK_06); | ||
554 | break; | ||
555 | |||
556 | case V4L2_CID_SATURATION: | ||
557 | val = saa7146_read(dev, BCS_CTRL); | ||
558 | val &= 0xffffff00; | ||
559 | val |= (ctrl->val << 0); | ||
560 | saa7146_write(dev, BCS_CTRL, val); | ||
561 | saa7146_write(dev, MC2, MASK_22 | MASK_06); | ||
562 | break; | ||
563 | |||
564 | case V4L2_CID_HFLIP: | ||
565 | /* fixme: we can support changing VFLIP and HFLIP here... */ | ||
566 | if ((vv->video_status & STATUS_CAPTURE)) | ||
567 | return -EBUSY; | ||
568 | vv->hflip = ctrl->val; | ||
569 | break; | ||
570 | |||
571 | case V4L2_CID_VFLIP: | ||
572 | if ((vv->video_status & STATUS_CAPTURE)) | ||
573 | return -EBUSY; | ||
574 | vv->vflip = ctrl->val; | ||
575 | break; | ||
576 | |||
577 | default: | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */ | ||
582 | struct saa7146_fh *fh = vv->video_fh; | ||
583 | |||
584 | saa7146_stop_preview(fh); | ||
585 | saa7146_start_preview(fh); | ||
586 | } | ||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | static int vidioc_g_parm(struct file *file, void *fh, | ||
591 | struct v4l2_streamparm *parm) | ||
592 | { | ||
593 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
594 | struct saa7146_vv *vv = dev->vv_data; | ||
595 | |||
596 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
597 | return -EINVAL; | ||
598 | parm->parm.capture.readbuffers = 1; | ||
599 | v4l2_video_std_frame_period(vv->standard->id, | ||
600 | &parm->parm.capture.timeperframe); | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | ||
605 | { | ||
606 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
607 | struct saa7146_vv *vv = dev->vv_data; | ||
608 | |||
609 | f->fmt.pix = vv->video_fmt; | ||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) | ||
614 | { | ||
615 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
616 | struct saa7146_vv *vv = dev->vv_data; | ||
617 | |||
618 | f->fmt.win = vv->ov.win; | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f) | ||
623 | { | ||
624 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
625 | struct saa7146_vv *vv = dev->vv_data; | ||
626 | |||
627 | f->fmt.vbi = vv->vbi_fmt; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | ||
632 | { | ||
633 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
634 | struct saa7146_vv *vv = dev->vv_data; | ||
635 | struct saa7146_format *fmt; | ||
636 | enum v4l2_field field; | ||
637 | int maxw, maxh; | ||
638 | int calc_bpl; | ||
639 | |||
640 | DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh); | ||
641 | |||
642 | fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat); | ||
643 | if (NULL == fmt) | ||
644 | return -EINVAL; | ||
645 | |||
646 | field = f->fmt.pix.field; | ||
647 | maxw = vv->standard->h_max_out; | ||
648 | maxh = vv->standard->v_max_out; | ||
649 | |||
650 | if (V4L2_FIELD_ANY == field) { | ||
651 | field = (f->fmt.pix.height > maxh / 2) | ||
652 | ? V4L2_FIELD_INTERLACED | ||
653 | : V4L2_FIELD_BOTTOM; | ||
654 | } | ||
655 | switch (field) { | ||
656 | case V4L2_FIELD_ALTERNATE: | ||
657 | vv->last_field = V4L2_FIELD_TOP; | ||
658 | maxh = maxh / 2; | ||
659 | break; | ||
660 | case V4L2_FIELD_TOP: | ||
661 | case V4L2_FIELD_BOTTOM: | ||
662 | vv->last_field = V4L2_FIELD_INTERLACED; | ||
663 | maxh = maxh / 2; | ||
664 | break; | ||
665 | case V4L2_FIELD_INTERLACED: | ||
666 | vv->last_field = V4L2_FIELD_INTERLACED; | ||
667 | break; | ||
668 | default: | ||
669 | DEB_D("no known field mode '%d'\n", field); | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | f->fmt.pix.field = field; | ||
674 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
675 | if (f->fmt.pix.width > maxw) | ||
676 | f->fmt.pix.width = maxw; | ||
677 | if (f->fmt.pix.height > maxh) | ||
678 | f->fmt.pix.height = maxh; | ||
679 | |||
680 | calc_bpl = (f->fmt.pix.width * fmt->depth) / 8; | ||
681 | |||
682 | if (f->fmt.pix.bytesperline < calc_bpl) | ||
683 | f->fmt.pix.bytesperline = calc_bpl; | ||
684 | |||
685 | if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */ | ||
686 | f->fmt.pix.bytesperline = calc_bpl; | ||
687 | |||
688 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; | ||
689 | DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", | ||
690 | f->fmt.pix.width, f->fmt.pix.height, | ||
691 | f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); | ||
692 | |||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | |||
697 | static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) | ||
698 | { | ||
699 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
700 | struct saa7146_vv *vv = dev->vv_data; | ||
701 | struct v4l2_window *win = &f->fmt.win; | ||
702 | enum v4l2_field field; | ||
703 | int maxw, maxh; | ||
704 | |||
705 | DEB_EE("dev:%p\n", dev); | ||
706 | |||
707 | if (NULL == vv->ov_fb.base) { | ||
708 | DEB_D("no fb base set\n"); | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | if (NULL == vv->ov_fmt) { | ||
712 | DEB_D("no fb fmt set\n"); | ||
713 | return -EINVAL; | ||
714 | } | ||
715 | if (win->w.width < 48 || win->w.height < 32) { | ||
716 | DEB_D("min width/height. (%d,%d)\n", | ||
717 | win->w.width, win->w.height); | ||
718 | return -EINVAL; | ||
719 | } | ||
720 | if (win->clipcount > 16) { | ||
721 | DEB_D("clipcount too big\n"); | ||
722 | return -EINVAL; | ||
723 | } | ||
724 | |||
725 | field = win->field; | ||
726 | maxw = vv->standard->h_max_out; | ||
727 | maxh = vv->standard->v_max_out; | ||
728 | |||
729 | if (V4L2_FIELD_ANY == field) { | ||
730 | field = (win->w.height > maxh / 2) | ||
731 | ? V4L2_FIELD_INTERLACED | ||
732 | : V4L2_FIELD_TOP; | ||
733 | } | ||
734 | switch (field) { | ||
735 | case V4L2_FIELD_TOP: | ||
736 | case V4L2_FIELD_BOTTOM: | ||
737 | case V4L2_FIELD_ALTERNATE: | ||
738 | maxh = maxh / 2; | ||
739 | break; | ||
740 | case V4L2_FIELD_INTERLACED: | ||
741 | break; | ||
742 | default: | ||
743 | DEB_D("no known field mode '%d'\n", field); | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | win->field = field; | ||
748 | if (win->w.width > maxw) | ||
749 | win->w.width = maxw; | ||
750 | if (win->w.height > maxh) | ||
751 | win->w.height = maxh; | ||
752 | |||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) | ||
757 | { | ||
758 | struct saa7146_fh *fh = __fh; | ||
759 | struct saa7146_dev *dev = fh->dev; | ||
760 | struct saa7146_vv *vv = dev->vv_data; | ||
761 | int err; | ||
762 | |||
763 | DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh); | ||
764 | if (IS_CAPTURE_ACTIVE(fh) != 0) { | ||
765 | DEB_EE("streaming capture is active\n"); | ||
766 | return -EBUSY; | ||
767 | } | ||
768 | err = vidioc_try_fmt_vid_cap(file, fh, f); | ||
769 | if (0 != err) | ||
770 | return err; | ||
771 | vv->video_fmt = f->fmt.pix; | ||
772 | DEB_EE("set to pixelformat '%4.4s'\n", | ||
773 | (char *)&vv->video_fmt.pixelformat); | ||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f) | ||
778 | { | ||
779 | struct saa7146_fh *fh = __fh; | ||
780 | struct saa7146_dev *dev = fh->dev; | ||
781 | struct saa7146_vv *vv = dev->vv_data; | ||
782 | int err; | ||
783 | |||
784 | DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh); | ||
785 | err = vidioc_try_fmt_vid_overlay(file, fh, f); | ||
786 | if (0 != err) | ||
787 | return err; | ||
788 | vv->ov.win = f->fmt.win; | ||
789 | vv->ov.nclips = f->fmt.win.clipcount; | ||
790 | if (vv->ov.nclips > 16) | ||
791 | vv->ov.nclips = 16; | ||
792 | if (copy_from_user(vv->ov.clips, f->fmt.win.clips, | ||
793 | sizeof(struct v4l2_clip) * vv->ov.nclips)) { | ||
794 | return -EFAULT; | ||
795 | } | ||
796 | |||
797 | /* vv->ov.fh is used to indicate that we have valid overlay informations, too */ | ||
798 | vv->ov.fh = fh; | ||
799 | |||
800 | /* check if our current overlay is active */ | ||
801 | if (IS_OVERLAY_ACTIVE(fh) != 0) { | ||
802 | saa7146_stop_preview(fh); | ||
803 | saa7146_start_preview(fh); | ||
804 | } | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm) | ||
809 | { | ||
810 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
811 | struct saa7146_vv *vv = dev->vv_data; | ||
812 | |||
813 | *norm = vv->standard->id; | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | /* the saa7146 supfhrts (used in conjunction with the saa7111a for example) | ||
818 | PAL / NTSC / SECAM. if your hardware does not (or does more) | ||
819 | -- override this function in your extension */ | ||
820 | /* | ||
821 | case VIDIOC_ENUMSTD: | ||
822 | { | ||
823 | struct v4l2_standard *e = arg; | ||
824 | if (e->index < 0 ) | ||
825 | return -EINVAL; | ||
826 | if( e->index < dev->ext_vv_data->num_stds ) { | ||
827 | DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index); | ||
828 | v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name); | ||
829 | return 0; | ||
830 | } | ||
831 | return -EINVAL; | ||
832 | } | ||
833 | */ | ||
834 | |||
835 | static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) | ||
836 | { | ||
837 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
838 | struct saa7146_vv *vv = dev->vv_data; | ||
839 | int found = 0; | ||
840 | int err, i; | ||
841 | |||
842 | DEB_EE("VIDIOC_S_STD\n"); | ||
843 | |||
844 | if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { | ||
845 | DEB_D("cannot change video standard while streaming capture is active\n"); | ||
846 | return -EBUSY; | ||
847 | } | ||
848 | |||
849 | if ((vv->video_status & STATUS_OVERLAY) != 0) { | ||
850 | vv->ov_suspend = vv->video_fh; | ||
851 | err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ | ||
852 | if (0 != err) { | ||
853 | DEB_D("suspending video failed. aborting\n"); | ||
854 | return err; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | for (i = 0; i < dev->ext_vv_data->num_stds; i++) | ||
859 | if (*id & dev->ext_vv_data->stds[i].id) | ||
860 | break; | ||
861 | if (i != dev->ext_vv_data->num_stds) { | ||
862 | vv->standard = &dev->ext_vv_data->stds[i]; | ||
863 | if (NULL != dev->ext_vv_data->std_callback) | ||
864 | dev->ext_vv_data->std_callback(dev, vv->standard); | ||
865 | found = 1; | ||
866 | } | ||
867 | |||
868 | if (vv->ov_suspend != NULL) { | ||
869 | saa7146_start_preview(vv->ov_suspend); | ||
870 | vv->ov_suspend = NULL; | ||
871 | } | ||
872 | |||
873 | if (!found) { | ||
874 | DEB_EE("VIDIOC_S_STD: standard not found\n"); | ||
875 | return -EINVAL; | ||
876 | } | ||
877 | |||
878 | DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name); | ||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | static int vidioc_overlay(struct file *file, void *fh, unsigned int on) | ||
883 | { | ||
884 | int err; | ||
885 | |||
886 | DEB_D("VIDIOC_OVERLAY on:%d\n", on); | ||
887 | if (on) | ||
888 | err = saa7146_start_preview(fh); | ||
889 | else | ||
890 | err = saa7146_stop_preview(fh); | ||
891 | return err; | ||
892 | } | ||
893 | |||
894 | static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b) | ||
895 | { | ||
896 | struct saa7146_fh *fh = __fh; | ||
897 | |||
898 | if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
899 | return videobuf_reqbufs(&fh->video_q, b); | ||
900 | if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
901 | return videobuf_reqbufs(&fh->vbi_q, b); | ||
902 | return -EINVAL; | ||
903 | } | ||
904 | |||
905 | static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) | ||
906 | { | ||
907 | struct saa7146_fh *fh = __fh; | ||
908 | |||
909 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
910 | return videobuf_querybuf(&fh->video_q, buf); | ||
911 | if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
912 | return videobuf_querybuf(&fh->vbi_q, buf); | ||
913 | return -EINVAL; | ||
914 | } | ||
915 | |||
916 | static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) | ||
917 | { | ||
918 | struct saa7146_fh *fh = __fh; | ||
919 | |||
920 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
921 | return videobuf_qbuf(&fh->video_q, buf); | ||
922 | if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
923 | return videobuf_qbuf(&fh->vbi_q, buf); | ||
924 | return -EINVAL; | ||
925 | } | ||
926 | |||
927 | static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) | ||
928 | { | ||
929 | struct saa7146_fh *fh = __fh; | ||
930 | |||
931 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
932 | return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK); | ||
933 | if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
934 | return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK); | ||
935 | return -EINVAL; | ||
936 | } | ||
937 | |||
938 | static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) | ||
939 | { | ||
940 | struct saa7146_fh *fh = __fh; | ||
941 | int err; | ||
942 | |||
943 | DEB_D("VIDIOC_STREAMON, type:%d\n", type); | ||
944 | |||
945 | err = video_begin(fh); | ||
946 | if (err) | ||
947 | return err; | ||
948 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
949 | return videobuf_streamon(&fh->video_q); | ||
950 | if (type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
951 | return videobuf_streamon(&fh->vbi_q); | ||
952 | return -EINVAL; | ||
953 | } | ||
954 | |||
955 | static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) | ||
956 | { | ||
957 | struct saa7146_fh *fh = __fh; | ||
958 | struct saa7146_dev *dev = fh->dev; | ||
959 | struct saa7146_vv *vv = dev->vv_data; | ||
960 | int err; | ||
961 | |||
962 | DEB_D("VIDIOC_STREAMOFF, type:%d\n", type); | ||
963 | |||
964 | /* ugly: we need to copy some checks from video_end(), | ||
965 | because videobuf_streamoff() relies on the capture running. | ||
966 | check and fix this */ | ||
967 | if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { | ||
968 | DEB_S("not capturing\n"); | ||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | if (vv->video_fh != fh) { | ||
973 | DEB_S("capturing, but in another open\n"); | ||
974 | return -EBUSY; | ||
975 | } | ||
976 | |||
977 | err = -EINVAL; | ||
978 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
979 | err = videobuf_streamoff(&fh->video_q); | ||
980 | else if (type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
981 | err = videobuf_streamoff(&fh->vbi_q); | ||
982 | if (0 != err) { | ||
983 | DEB_D("warning: videobuf_streamoff() failed\n"); | ||
984 | video_end(fh, file); | ||
985 | } else { | ||
986 | err = video_end(fh, file); | ||
987 | } | ||
988 | return err; | ||
989 | } | ||
990 | |||
991 | static int vidioc_g_chip_ident(struct file *file, void *__fh, | ||
992 | struct v4l2_dbg_chip_ident *chip) | ||
993 | { | ||
994 | struct saa7146_fh *fh = __fh; | ||
995 | struct saa7146_dev *dev = fh->dev; | ||
996 | |||
997 | chip->ident = V4L2_IDENT_NONE; | ||
998 | chip->revision = 0; | ||
999 | if (chip->match.type == V4L2_CHIP_MATCH_HOST) { | ||
1000 | if (v4l2_chip_match_host(&chip->match)) | ||
1001 | chip->ident = V4L2_IDENT_SAA7146; | ||
1002 | return 0; | ||
1003 | } | ||
1004 | if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && | ||
1005 | chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
1006 | return -EINVAL; | ||
1007 | return v4l2_device_call_until_err(&dev->v4l2_dev, 0, | ||
1008 | core, g_chip_ident, chip); | ||
1009 | } | ||
1010 | |||
1011 | const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { | ||
1012 | .vidioc_querycap = vidioc_querycap, | ||
1013 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
1014 | .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap, | ||
1015 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
1016 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
1017 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
1018 | .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, | ||
1019 | .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, | ||
1020 | .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, | ||
1021 | .vidioc_g_chip_ident = vidioc_g_chip_ident, | ||
1022 | |||
1023 | .vidioc_overlay = vidioc_overlay, | ||
1024 | .vidioc_g_fbuf = vidioc_g_fbuf, | ||
1025 | .vidioc_s_fbuf = vidioc_s_fbuf, | ||
1026 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1027 | .vidioc_querybuf = vidioc_querybuf, | ||
1028 | .vidioc_qbuf = vidioc_qbuf, | ||
1029 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1030 | .vidioc_g_std = vidioc_g_std, | ||
1031 | .vidioc_s_std = vidioc_s_std, | ||
1032 | .vidioc_streamon = vidioc_streamon, | ||
1033 | .vidioc_streamoff = vidioc_streamoff, | ||
1034 | .vidioc_g_parm = vidioc_g_parm, | ||
1035 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
1036 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
1037 | }; | ||
1038 | |||
1039 | const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = { | ||
1040 | .vidioc_querycap = vidioc_querycap, | ||
1041 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, | ||
1042 | .vidioc_g_chip_ident = vidioc_g_chip_ident, | ||
1043 | |||
1044 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1045 | .vidioc_querybuf = vidioc_querybuf, | ||
1046 | .vidioc_qbuf = vidioc_qbuf, | ||
1047 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1048 | .vidioc_g_std = vidioc_g_std, | ||
1049 | .vidioc_s_std = vidioc_s_std, | ||
1050 | .vidioc_streamon = vidioc_streamon, | ||
1051 | .vidioc_streamoff = vidioc_streamoff, | ||
1052 | .vidioc_g_parm = vidioc_g_parm, | ||
1053 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
1054 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
1055 | }; | ||
1056 | |||
1057 | /*********************************************************************************/ | ||
1058 | /* buffer handling functions */ | ||
1059 | |||
1060 | static int buffer_activate (struct saa7146_dev *dev, | ||
1061 | struct saa7146_buf *buf, | ||
1062 | struct saa7146_buf *next) | ||
1063 | { | ||
1064 | struct saa7146_vv *vv = dev->vv_data; | ||
1065 | |||
1066 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
1067 | saa7146_set_capture(dev,buf,next); | ||
1068 | |||
1069 | mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT); | ||
1070 | return 0; | ||
1071 | } | ||
1072 | |||
1073 | static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf) | ||
1074 | { | ||
1075 | saa7146_pgtable_free(dev->pci, &buf->pt[0]); | ||
1076 | saa7146_pgtable_free(dev->pci, &buf->pt[1]); | ||
1077 | saa7146_pgtable_free(dev->pci, &buf->pt[2]); | ||
1078 | } | ||
1079 | |||
1080 | static int buffer_prepare(struct videobuf_queue *q, | ||
1081 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
1082 | { | ||
1083 | struct file *file = q->priv_data; | ||
1084 | struct saa7146_fh *fh = file->private_data; | ||
1085 | struct saa7146_dev *dev = fh->dev; | ||
1086 | struct saa7146_vv *vv = dev->vv_data; | ||
1087 | struct saa7146_buf *buf = (struct saa7146_buf *)vb; | ||
1088 | int size,err = 0; | ||
1089 | |||
1090 | DEB_CAP("vbuf:%p\n", vb); | ||
1091 | |||
1092 | /* sanity checks */ | ||
1093 | if (vv->video_fmt.width < 48 || | ||
1094 | vv->video_fmt.height < 32 || | ||
1095 | vv->video_fmt.width > vv->standard->h_max_out || | ||
1096 | vv->video_fmt.height > vv->standard->v_max_out) { | ||
1097 | DEB_D("w (%d) / h (%d) out of bounds\n", | ||
1098 | vv->video_fmt.width, vv->video_fmt.height); | ||
1099 | return -EINVAL; | ||
1100 | } | ||
1101 | |||
1102 | size = vv->video_fmt.sizeimage; | ||
1103 | if (0 != buf->vb.baddr && buf->vb.bsize < size) { | ||
1104 | DEB_D("size mismatch\n"); | ||
1105 | return -EINVAL; | ||
1106 | } | ||
1107 | |||
1108 | DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n", | ||
1109 | vv->video_fmt.width, vv->video_fmt.height, | ||
1110 | size, v4l2_field_names[vv->video_fmt.field]); | ||
1111 | if (buf->vb.width != vv->video_fmt.width || | ||
1112 | buf->vb.bytesperline != vv->video_fmt.bytesperline || | ||
1113 | buf->vb.height != vv->video_fmt.height || | ||
1114 | buf->vb.size != size || | ||
1115 | buf->vb.field != field || | ||
1116 | buf->vb.field != vv->video_fmt.field || | ||
1117 | buf->fmt != &vv->video_fmt) { | ||
1118 | saa7146_dma_free(dev,q,buf); | ||
1119 | } | ||
1120 | |||
1121 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | ||
1122 | struct saa7146_format *sfmt; | ||
1123 | |||
1124 | buf->vb.bytesperline = vv->video_fmt.bytesperline; | ||
1125 | buf->vb.width = vv->video_fmt.width; | ||
1126 | buf->vb.height = vv->video_fmt.height; | ||
1127 | buf->vb.size = size; | ||
1128 | buf->vb.field = field; | ||
1129 | buf->fmt = &vv->video_fmt; | ||
1130 | buf->vb.field = vv->video_fmt.field; | ||
1131 | |||
1132 | sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); | ||
1133 | |||
1134 | release_all_pagetables(dev, buf); | ||
1135 | if( 0 != IS_PLANAR(sfmt->trans)) { | ||
1136 | saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); | ||
1137 | saa7146_pgtable_alloc(dev->pci, &buf->pt[1]); | ||
1138 | saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); | ||
1139 | } else { | ||
1140 | saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); | ||
1141 | } | ||
1142 | |||
1143 | err = videobuf_iolock(q,&buf->vb, &vv->ov_fb); | ||
1144 | if (err) | ||
1145 | goto oops; | ||
1146 | err = saa7146_pgtable_build(dev,buf); | ||
1147 | if (err) | ||
1148 | goto oops; | ||
1149 | } | ||
1150 | buf->vb.state = VIDEOBUF_PREPARED; | ||
1151 | buf->activate = buffer_activate; | ||
1152 | |||
1153 | return 0; | ||
1154 | |||
1155 | oops: | ||
1156 | DEB_D("error out\n"); | ||
1157 | saa7146_dma_free(dev,q,buf); | ||
1158 | |||
1159 | return err; | ||
1160 | } | ||
1161 | |||
1162 | static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | ||
1163 | { | ||
1164 | struct file *file = q->priv_data; | ||
1165 | struct saa7146_fh *fh = file->private_data; | ||
1166 | struct saa7146_vv *vv = fh->dev->vv_data; | ||
1167 | |||
1168 | if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS) | ||
1169 | *count = MAX_SAA7146_CAPTURE_BUFFERS; | ||
1170 | |||
1171 | *size = vv->video_fmt.sizeimage; | ||
1172 | |||
1173 | /* check if we exceed the "max_memory" parameter */ | ||
1174 | if( (*count * *size) > (max_memory*1048576) ) { | ||
1175 | *count = (max_memory*1048576) / *size; | ||
1176 | } | ||
1177 | |||
1178 | DEB_CAP("%d buffers, %d bytes each\n", *count, *size); | ||
1179 | |||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
1184 | { | ||
1185 | struct file *file = q->priv_data; | ||
1186 | struct saa7146_fh *fh = file->private_data; | ||
1187 | struct saa7146_dev *dev = fh->dev; | ||
1188 | struct saa7146_vv *vv = dev->vv_data; | ||
1189 | struct saa7146_buf *buf = (struct saa7146_buf *)vb; | ||
1190 | |||
1191 | DEB_CAP("vbuf:%p\n", vb); | ||
1192 | saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf); | ||
1193 | } | ||
1194 | |||
1195 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
1196 | { | ||
1197 | struct file *file = q->priv_data; | ||
1198 | struct saa7146_fh *fh = file->private_data; | ||
1199 | struct saa7146_dev *dev = fh->dev; | ||
1200 | struct saa7146_buf *buf = (struct saa7146_buf *)vb; | ||
1201 | |||
1202 | DEB_CAP("vbuf:%p\n", vb); | ||
1203 | |||
1204 | saa7146_dma_free(dev,q,buf); | ||
1205 | |||
1206 | release_all_pagetables(dev, buf); | ||
1207 | } | ||
1208 | |||
1209 | static struct videobuf_queue_ops video_qops = { | ||
1210 | .buf_setup = buffer_setup, | ||
1211 | .buf_prepare = buffer_prepare, | ||
1212 | .buf_queue = buffer_queue, | ||
1213 | .buf_release = buffer_release, | ||
1214 | }; | ||
1215 | |||
1216 | /********************************************************************************/ | ||
1217 | /* file operations */ | ||
1218 | |||
1219 | static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) | ||
1220 | { | ||
1221 | INIT_LIST_HEAD(&vv->video_dmaq.queue); | ||
1222 | |||
1223 | init_timer(&vv->video_dmaq.timeout); | ||
1224 | vv->video_dmaq.timeout.function = saa7146_buffer_timeout; | ||
1225 | vv->video_dmaq.timeout.data = (unsigned long)(&vv->video_dmaq); | ||
1226 | vv->video_dmaq.dev = dev; | ||
1227 | |||
1228 | /* set some default values */ | ||
1229 | vv->standard = &dev->ext_vv_data->stds[0]; | ||
1230 | |||
1231 | /* FIXME: what's this? */ | ||
1232 | vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; | ||
1233 | vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; | ||
1234 | } | ||
1235 | |||
1236 | |||
1237 | static int video_open(struct saa7146_dev *dev, struct file *file) | ||
1238 | { | ||
1239 | struct saa7146_fh *fh = file->private_data; | ||
1240 | |||
1241 | videobuf_queue_sg_init(&fh->video_q, &video_qops, | ||
1242 | &dev->pci->dev, &dev->slock, | ||
1243 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1244 | V4L2_FIELD_INTERLACED, | ||
1245 | sizeof(struct saa7146_buf), | ||
1246 | file, &dev->v4l2_lock); | ||
1247 | |||
1248 | return 0; | ||
1249 | } | ||
1250 | |||
1251 | |||
1252 | static void video_close(struct saa7146_dev *dev, struct file *file) | ||
1253 | { | ||
1254 | struct saa7146_fh *fh = file->private_data; | ||
1255 | struct saa7146_vv *vv = dev->vv_data; | ||
1256 | struct videobuf_queue *q = &fh->video_q; | ||
1257 | |||
1258 | if (IS_CAPTURE_ACTIVE(fh) != 0) | ||
1259 | video_end(fh, file); | ||
1260 | else if (IS_OVERLAY_ACTIVE(fh) != 0) | ||
1261 | saa7146_stop_preview(fh); | ||
1262 | |||
1263 | videobuf_stop(q); | ||
1264 | /* hmm, why is this function declared void? */ | ||
1265 | } | ||
1266 | |||
1267 | |||
1268 | static void video_irq_done(struct saa7146_dev *dev, unsigned long st) | ||
1269 | { | ||
1270 | struct saa7146_vv *vv = dev->vv_data; | ||
1271 | struct saa7146_dmaqueue *q = &vv->video_dmaq; | ||
1272 | |||
1273 | spin_lock(&dev->slock); | ||
1274 | DEB_CAP("called\n"); | ||
1275 | |||
1276 | /* only finish the buffer if we have one... */ | ||
1277 | if( NULL != q->curr ) { | ||
1278 | saa7146_buffer_finish(dev,q,VIDEOBUF_DONE); | ||
1279 | } | ||
1280 | saa7146_buffer_next(dev,q,0); | ||
1281 | |||
1282 | spin_unlock(&dev->slock); | ||
1283 | } | ||
1284 | |||
1285 | static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
1286 | { | ||
1287 | struct saa7146_fh *fh = file->private_data; | ||
1288 | struct saa7146_dev *dev = fh->dev; | ||
1289 | struct saa7146_vv *vv = dev->vv_data; | ||
1290 | ssize_t ret = 0; | ||
1291 | |||
1292 | DEB_EE("called\n"); | ||
1293 | |||
1294 | if ((vv->video_status & STATUS_CAPTURE) != 0) { | ||
1295 | /* fixme: should we allow read() captures while streaming capture? */ | ||
1296 | if (vv->video_fh == fh) { | ||
1297 | DEB_S("already capturing\n"); | ||
1298 | return -EBUSY; | ||
1299 | } | ||
1300 | DEB_S("already capturing in another open\n"); | ||
1301 | return -EBUSY; | ||
1302 | } | ||
1303 | |||
1304 | ret = video_begin(fh); | ||
1305 | if( 0 != ret) { | ||
1306 | goto out; | ||
1307 | } | ||
1308 | |||
1309 | ret = videobuf_read_one(&fh->video_q , data, count, ppos, | ||
1310 | file->f_flags & O_NONBLOCK); | ||
1311 | if (ret != 0) { | ||
1312 | video_end(fh, file); | ||
1313 | } else { | ||
1314 | ret = video_end(fh, file); | ||
1315 | } | ||
1316 | out: | ||
1317 | /* restart overlay if it was active before */ | ||
1318 | if (vv->ov_suspend != NULL) { | ||
1319 | saa7146_start_preview(vv->ov_suspend); | ||
1320 | vv->ov_suspend = NULL; | ||
1321 | } | ||
1322 | |||
1323 | return ret; | ||
1324 | } | ||
1325 | |||
1326 | struct saa7146_use_ops saa7146_video_uops = { | ||
1327 | .init = video_init, | ||
1328 | .open = video_open, | ||
1329 | .release = video_close, | ||
1330 | .irq_done = video_irq_done, | ||
1331 | .read = video_read, | ||
1332 | }; | ||
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig deleted file mode 100644 index 68f0f604678..00000000000 --- a/drivers/media/common/siano/Kconfig +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | # | ||
2 | # Siano Mobile Silicon Digital TV device configuration | ||
3 | # | ||
4 | |||
5 | config SMS_SIANO_MDTV | ||
6 | tristate | ||
7 | depends on DVB_CORE && HAS_DMA | ||
8 | depends on !RC_CORE || RC_CORE | ||
9 | depends on SMS_USB_DRV || SMS_SDIO_DRV | ||
10 | default y | ||
11 | |||
12 | config SMS_SIANO_RC | ||
13 | bool "Enable Remote Controller support for Siano devices" | ||
14 | depends on SMS_SIANO_MDTV && RC_CORE | ||
15 | depends on SMS_USB_DRV || SMS_SDIO_DRV | ||
16 | depends on MEDIA_COMMON_OPTIONS | ||
17 | default y | ||
18 | ---help--- | ||
19 | Choose Y to select Remote Controller support for Siano driver. | ||
diff --git a/drivers/media/common/siano/Makefile b/drivers/media/common/siano/Makefile deleted file mode 100644 index 81b1e985bea..00000000000 --- a/drivers/media/common/siano/Makefile +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o | ||
2 | |||
3 | obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o | ||
4 | |||
5 | ifeq ($(CONFIG_SMS_SIANO_RC),y) | ||
6 | smsmdtv-objs += smsir.o | ||
7 | endif | ||
8 | |||
9 | ccflags-y += -Idrivers/media/dvb-core | ||
10 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | ||
11 | |||
diff --git a/drivers/media/common/siano/sms-cards.c b/drivers/media/common/siano/sms-cards.c deleted file mode 100644 index 680c781c8dd..00000000000 --- a/drivers/media/common/siano/sms-cards.c +++ /dev/null | |||
@@ -1,311 +0,0 @@ | |||
1 | /* | ||
2 | * Card-specific functions for the Siano SMS1xxx USB dongle | ||
3 | * | ||
4 | * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation; | ||
9 | * | ||
10 | * Software distributed under the License is distributed on an "AS IS" | ||
11 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | ||
12 | * | ||
13 | * See the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include "sms-cards.h" | ||
21 | #include "smsir.h" | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | static int sms_dbg; | ||
25 | module_param_named(cards_dbg, sms_dbg, int, 0644); | ||
26 | MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))"); | ||
27 | |||
28 | static struct sms_board sms_boards[] = { | ||
29 | [SMS_BOARD_UNKNOWN] = { | ||
30 | .name = "Unknown board", | ||
31 | }, | ||
32 | [SMS1XXX_BOARD_SIANO_STELLAR] = { | ||
33 | .name = "Siano Stellar Digital Receiver", | ||
34 | .type = SMS_STELLAR, | ||
35 | }, | ||
36 | [SMS1XXX_BOARD_SIANO_NOVA_A] = { | ||
37 | .name = "Siano Nova A Digital Receiver", | ||
38 | .type = SMS_NOVA_A0, | ||
39 | }, | ||
40 | [SMS1XXX_BOARD_SIANO_NOVA_B] = { | ||
41 | .name = "Siano Nova B Digital Receiver", | ||
42 | .type = SMS_NOVA_B0, | ||
43 | }, | ||
44 | [SMS1XXX_BOARD_SIANO_VEGA] = { | ||
45 | .name = "Siano Vega Digital Receiver", | ||
46 | .type = SMS_VEGA, | ||
47 | }, | ||
48 | [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = { | ||
49 | .name = "Hauppauge Catamount", | ||
50 | .type = SMS_STELLAR, | ||
51 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw", | ||
52 | }, | ||
53 | [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = { | ||
54 | .name = "Hauppauge Okemo-A", | ||
55 | .type = SMS_NOVA_A0, | ||
56 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw", | ||
57 | }, | ||
58 | [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = { | ||
59 | .name = "Hauppauge Okemo-B", | ||
60 | .type = SMS_NOVA_B0, | ||
61 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw", | ||
62 | }, | ||
63 | [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { | ||
64 | .name = "Hauppauge WinTV MiniStick", | ||
65 | .type = SMS_NOVA_B0, | ||
66 | .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", | ||
67 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | ||
68 | .rc_codes = RC_MAP_HAUPPAUGE, | ||
69 | .board_cfg.leds_power = 26, | ||
70 | .board_cfg.led0 = 27, | ||
71 | .board_cfg.led1 = 28, | ||
72 | .board_cfg.ir = 9, | ||
73 | .led_power = 26, | ||
74 | .led_lo = 27, | ||
75 | .led_hi = 28, | ||
76 | }, | ||
77 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = { | ||
78 | .name = "Hauppauge WinTV MiniCard", | ||
79 | .type = SMS_NOVA_B0, | ||
80 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | ||
81 | .lna_ctrl = 29, | ||
82 | .board_cfg.foreign_lna0_ctrl = 29, | ||
83 | .rf_switch = 17, | ||
84 | .board_cfg.rf_switch_uhf = 17, | ||
85 | }, | ||
86 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { | ||
87 | .name = "Hauppauge WinTV MiniCard", | ||
88 | .type = SMS_NOVA_B0, | ||
89 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | ||
90 | .lna_ctrl = -1, | ||
91 | }, | ||
92 | [SMS1XXX_BOARD_SIANO_NICE] = { | ||
93 | /* 11 */ | ||
94 | .name = "Siano Nice Digital Receiver", | ||
95 | .type = SMS_NOVA_B0, | ||
96 | }, | ||
97 | [SMS1XXX_BOARD_SIANO_VENICE] = { | ||
98 | /* 12 */ | ||
99 | .name = "Siano Venice Digital Receiver", | ||
100 | .type = SMS_VEGA, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | struct sms_board *sms_get_board(unsigned id) | ||
105 | { | ||
106 | BUG_ON(id >= ARRAY_SIZE(sms_boards)); | ||
107 | |||
108 | return &sms_boards[id]; | ||
109 | } | ||
110 | EXPORT_SYMBOL_GPL(sms_get_board); | ||
111 | static inline void sms_gpio_assign_11xx_default_led_config( | ||
112 | struct smscore_gpio_config *pGpioConfig) { | ||
113 | pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT; | ||
114 | pGpioConfig->InputCharacteristics = | ||
115 | SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL; | ||
116 | pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA; | ||
117 | pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS; | ||
118 | pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE; | ||
119 | } | ||
120 | |||
121 | int sms_board_event(struct smscore_device_t *coredev, | ||
122 | enum SMS_BOARD_EVENTS gevent) { | ||
123 | struct smscore_gpio_config MyGpioConfig; | ||
124 | |||
125 | sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); | ||
126 | |||
127 | switch (gevent) { | ||
128 | case BOARD_EVENT_POWER_INIT: /* including hotplug */ | ||
129 | break; /* BOARD_EVENT_BIND */ | ||
130 | |||
131 | case BOARD_EVENT_POWER_SUSPEND: | ||
132 | break; /* BOARD_EVENT_POWER_SUSPEND */ | ||
133 | |||
134 | case BOARD_EVENT_POWER_RESUME: | ||
135 | break; /* BOARD_EVENT_POWER_RESUME */ | ||
136 | |||
137 | case BOARD_EVENT_BIND: | ||
138 | break; /* BOARD_EVENT_BIND */ | ||
139 | |||
140 | case BOARD_EVENT_SCAN_PROG: | ||
141 | break; /* BOARD_EVENT_SCAN_PROG */ | ||
142 | case BOARD_EVENT_SCAN_COMP: | ||
143 | break; /* BOARD_EVENT_SCAN_COMP */ | ||
144 | case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: | ||
145 | break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ | ||
146 | case BOARD_EVENT_FE_LOCK: | ||
147 | break; /* BOARD_EVENT_FE_LOCK */ | ||
148 | case BOARD_EVENT_FE_UNLOCK: | ||
149 | break; /* BOARD_EVENT_FE_UNLOCK */ | ||
150 | case BOARD_EVENT_DEMOD_LOCK: | ||
151 | break; /* BOARD_EVENT_DEMOD_LOCK */ | ||
152 | case BOARD_EVENT_DEMOD_UNLOCK: | ||
153 | break; /* BOARD_EVENT_DEMOD_UNLOCK */ | ||
154 | case BOARD_EVENT_RECEPTION_MAX_4: | ||
155 | break; /* BOARD_EVENT_RECEPTION_MAX_4 */ | ||
156 | case BOARD_EVENT_RECEPTION_3: | ||
157 | break; /* BOARD_EVENT_RECEPTION_3 */ | ||
158 | case BOARD_EVENT_RECEPTION_2: | ||
159 | break; /* BOARD_EVENT_RECEPTION_2 */ | ||
160 | case BOARD_EVENT_RECEPTION_1: | ||
161 | break; /* BOARD_EVENT_RECEPTION_1 */ | ||
162 | case BOARD_EVENT_RECEPTION_LOST_0: | ||
163 | break; /* BOARD_EVENT_RECEPTION_LOST_0 */ | ||
164 | case BOARD_EVENT_MULTIPLEX_OK: | ||
165 | break; /* BOARD_EVENT_MULTIPLEX_OK */ | ||
166 | case BOARD_EVENT_MULTIPLEX_ERRORS: | ||
167 | break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ | ||
168 | |||
169 | default: | ||
170 | sms_err("Unknown SMS board event"); | ||
171 | break; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(sms_board_event); | ||
176 | |||
177 | static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) | ||
178 | { | ||
179 | int lvl, ret; | ||
180 | u32 gpio; | ||
181 | struct smscore_config_gpio gpioconfig = { | ||
182 | .direction = SMS_GPIO_DIRECTION_OUTPUT, | ||
183 | .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, | ||
184 | .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, | ||
185 | .outputslewrate = SMS_GPIO_OUTPUTSLEWRATE_FAST, | ||
186 | .outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA, | ||
187 | }; | ||
188 | |||
189 | if (pin == 0) | ||
190 | return -EINVAL; | ||
191 | |||
192 | if (pin < 0) { | ||
193 | /* inverted gpio */ | ||
194 | gpio = pin * -1; | ||
195 | lvl = enable ? 0 : 1; | ||
196 | } else { | ||
197 | gpio = pin; | ||
198 | lvl = enable ? 1 : 0; | ||
199 | } | ||
200 | |||
201 | ret = smscore_configure_gpio(coredev, gpio, &gpioconfig); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | return smscore_set_gpio(coredev, gpio, lvl); | ||
206 | } | ||
207 | |||
208 | int sms_board_setup(struct smscore_device_t *coredev) | ||
209 | { | ||
210 | int board_id = smscore_get_board_id(coredev); | ||
211 | struct sms_board *board = sms_get_board(board_id); | ||
212 | |||
213 | switch (board_id) { | ||
214 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
215 | /* turn off all LEDs */ | ||
216 | sms_set_gpio(coredev, board->led_power, 0); | ||
217 | sms_set_gpio(coredev, board->led_hi, 0); | ||
218 | sms_set_gpio(coredev, board->led_lo, 0); | ||
219 | break; | ||
220 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
221 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
222 | /* turn off LNA */ | ||
223 | sms_set_gpio(coredev, board->lna_ctrl, 0); | ||
224 | break; | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(sms_board_setup); | ||
229 | |||
230 | int sms_board_power(struct smscore_device_t *coredev, int onoff) | ||
231 | { | ||
232 | int board_id = smscore_get_board_id(coredev); | ||
233 | struct sms_board *board = sms_get_board(board_id); | ||
234 | |||
235 | switch (board_id) { | ||
236 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
237 | /* power LED */ | ||
238 | sms_set_gpio(coredev, | ||
239 | board->led_power, onoff ? 1 : 0); | ||
240 | break; | ||
241 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
242 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
243 | /* LNA */ | ||
244 | if (!onoff) | ||
245 | sms_set_gpio(coredev, board->lna_ctrl, 0); | ||
246 | break; | ||
247 | } | ||
248 | return 0; | ||
249 | } | ||
250 | EXPORT_SYMBOL_GPL(sms_board_power); | ||
251 | |||
252 | int sms_board_led_feedback(struct smscore_device_t *coredev, int led) | ||
253 | { | ||
254 | int board_id = smscore_get_board_id(coredev); | ||
255 | struct sms_board *board = sms_get_board(board_id); | ||
256 | |||
257 | /* dont touch GPIO if LEDs are already set */ | ||
258 | if (smscore_led_state(coredev, -1) == led) | ||
259 | return 0; | ||
260 | |||
261 | switch (board_id) { | ||
262 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
263 | sms_set_gpio(coredev, | ||
264 | board->led_lo, (led & SMS_LED_LO) ? 1 : 0); | ||
265 | sms_set_gpio(coredev, | ||
266 | board->led_hi, (led & SMS_LED_HI) ? 1 : 0); | ||
267 | |||
268 | smscore_led_state(coredev, led); | ||
269 | break; | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | EXPORT_SYMBOL_GPL(sms_board_led_feedback); | ||
274 | |||
275 | int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) | ||
276 | { | ||
277 | int board_id = smscore_get_board_id(coredev); | ||
278 | struct sms_board *board = sms_get_board(board_id); | ||
279 | |||
280 | sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled"); | ||
281 | |||
282 | switch (board_id) { | ||
283 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
284 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
285 | sms_set_gpio(coredev, | ||
286 | board->rf_switch, onoff ? 1 : 0); | ||
287 | return sms_set_gpio(coredev, | ||
288 | board->lna_ctrl, onoff ? 1 : 0); | ||
289 | } | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | EXPORT_SYMBOL_GPL(sms_board_lna_control); | ||
293 | |||
294 | int sms_board_load_modules(int id) | ||
295 | { | ||
296 | switch (id) { | ||
297 | case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT: | ||
298 | case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A: | ||
299 | case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B: | ||
300 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
301 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
302 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
303 | request_module("smsdvb"); | ||
304 | break; | ||
305 | default: | ||
306 | /* do nothing */ | ||
307 | break; | ||
308 | } | ||
309 | return 0; | ||
310 | } | ||
311 | EXPORT_SYMBOL_GPL(sms_board_load_modules); | ||
diff --git a/drivers/media/common/siano/sms-cards.h b/drivers/media/common/siano/sms-cards.h deleted file mode 100644 index d8cdf756f7c..00000000000 --- a/drivers/media/common/siano/sms-cards.h +++ /dev/null | |||
@@ -1,123 +0,0 @@ | |||
1 | /* | ||
2 | * Card-specific functions for the Siano SMS1xxx USB dongle | ||
3 | * | ||
4 | * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation; | ||
9 | * | ||
10 | * Software distributed under the License is distributed on an "AS IS" | ||
11 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | ||
12 | * | ||
13 | * See the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef __SMS_CARDS_H__ | ||
21 | #define __SMS_CARDS_H__ | ||
22 | |||
23 | #include <linux/usb.h> | ||
24 | #include "smscoreapi.h" | ||
25 | #include "smsir.h" | ||
26 | |||
27 | #define SMS_BOARD_UNKNOWN 0 | ||
28 | #define SMS1XXX_BOARD_SIANO_STELLAR 1 | ||
29 | #define SMS1XXX_BOARD_SIANO_NOVA_A 2 | ||
30 | #define SMS1XXX_BOARD_SIANO_NOVA_B 3 | ||
31 | #define SMS1XXX_BOARD_SIANO_VEGA 4 | ||
32 | #define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5 | ||
33 | #define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6 | ||
34 | #define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7 | ||
35 | #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8 | ||
36 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 | ||
37 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 | ||
38 | #define SMS1XXX_BOARD_SIANO_NICE 11 | ||
39 | #define SMS1XXX_BOARD_SIANO_VENICE 12 | ||
40 | |||
41 | struct sms_board_gpio_cfg { | ||
42 | int lna_vhf_exist; | ||
43 | int lna_vhf_ctrl; | ||
44 | int lna_uhf_exist; | ||
45 | int lna_uhf_ctrl; | ||
46 | int lna_uhf_d_ctrl; | ||
47 | int lna_sband_exist; | ||
48 | int lna_sband_ctrl; | ||
49 | int lna_sband_d_ctrl; | ||
50 | int foreign_lna0_ctrl; | ||
51 | int foreign_lna1_ctrl; | ||
52 | int foreign_lna2_ctrl; | ||
53 | int rf_switch_vhf; | ||
54 | int rf_switch_uhf; | ||
55 | int rf_switch_sband; | ||
56 | int leds_power; | ||
57 | int led0; | ||
58 | int led1; | ||
59 | int led2; | ||
60 | int led3; | ||
61 | int led4; | ||
62 | int ir; | ||
63 | int eeprom_wp; | ||
64 | int mrc_sense; | ||
65 | int mrc_pdn_resetn; | ||
66 | int mrc_gp0; /* mrcs spi int */ | ||
67 | int mrc_gp1; | ||
68 | int mrc_gp2; | ||
69 | int mrc_gp3; | ||
70 | int mrc_gp4; | ||
71 | int host_spi_gsp_ts_int; | ||
72 | }; | ||
73 | |||
74 | struct sms_board { | ||
75 | enum sms_device_type_st type; | ||
76 | char *name, *fw[DEVICE_MODE_MAX]; | ||
77 | struct sms_board_gpio_cfg board_cfg; | ||
78 | char *rc_codes; /* Name of IR codes table */ | ||
79 | |||
80 | /* gpios */ | ||
81 | int led_power, led_hi, led_lo, lna_ctrl, rf_switch; | ||
82 | }; | ||
83 | |||
84 | struct sms_board *sms_get_board(unsigned id); | ||
85 | |||
86 | extern struct smscore_device_t *coredev; | ||
87 | |||
88 | enum SMS_BOARD_EVENTS { | ||
89 | BOARD_EVENT_POWER_INIT, | ||
90 | BOARD_EVENT_POWER_SUSPEND, | ||
91 | BOARD_EVENT_POWER_RESUME, | ||
92 | BOARD_EVENT_BIND, | ||
93 | BOARD_EVENT_SCAN_PROG, | ||
94 | BOARD_EVENT_SCAN_COMP, | ||
95 | BOARD_EVENT_EMERGENCY_WARNING_SIGNAL, | ||
96 | BOARD_EVENT_FE_LOCK, | ||
97 | BOARD_EVENT_FE_UNLOCK, | ||
98 | BOARD_EVENT_DEMOD_LOCK, | ||
99 | BOARD_EVENT_DEMOD_UNLOCK, | ||
100 | BOARD_EVENT_RECEPTION_MAX_4, | ||
101 | BOARD_EVENT_RECEPTION_3, | ||
102 | BOARD_EVENT_RECEPTION_2, | ||
103 | BOARD_EVENT_RECEPTION_1, | ||
104 | BOARD_EVENT_RECEPTION_LOST_0, | ||
105 | BOARD_EVENT_MULTIPLEX_OK, | ||
106 | BOARD_EVENT_MULTIPLEX_ERRORS | ||
107 | }; | ||
108 | |||
109 | int sms_board_event(struct smscore_device_t *coredev, | ||
110 | enum SMS_BOARD_EVENTS gevent); | ||
111 | |||
112 | int sms_board_setup(struct smscore_device_t *coredev); | ||
113 | |||
114 | #define SMS_LED_OFF 0 | ||
115 | #define SMS_LED_LO 1 | ||
116 | #define SMS_LED_HI 2 | ||
117 | int sms_board_led_feedback(struct smscore_device_t *coredev, int led); | ||
118 | int sms_board_power(struct smscore_device_t *coredev, int onoff); | ||
119 | int sms_board_lna_control(struct smscore_device_t *coredev, int onoff); | ||
120 | |||
121 | extern int sms_board_load_modules(int id); | ||
122 | |||
123 | #endif /* __SMS_CARDS_H__ */ | ||
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c deleted file mode 100644 index 1842e64e633..00000000000 --- a/drivers/media/common/siano/smscoreapi.c +++ /dev/null | |||
@@ -1,1637 +0,0 @@ | |||
1 | /* | ||
2 | * Siano core API module | ||
3 | * | ||
4 | * This file contains implementation for the interface to sms core component | ||
5 | * | ||
6 | * author: Uri Shkolnik | ||
7 | * | ||
8 | * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation; | ||
13 | * | ||
14 | * Software distributed under the License is distributed on an "AS IS" | ||
15 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | ||
16 | * | ||
17 | * See the GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <linux/slab.h> | ||
32 | |||
33 | #include <linux/firmware.h> | ||
34 | #include <linux/wait.h> | ||
35 | #include <asm/byteorder.h> | ||
36 | |||
37 | #include "smscoreapi.h" | ||
38 | #include "sms-cards.h" | ||
39 | #include "smsir.h" | ||
40 | #include "smsendian.h" | ||
41 | |||
42 | static int sms_dbg; | ||
43 | module_param_named(debug, sms_dbg, int, 0644); | ||
44 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | ||
45 | |||
46 | struct smscore_device_notifyee_t { | ||
47 | struct list_head entry; | ||
48 | hotplug_t hotplug; | ||
49 | }; | ||
50 | |||
51 | struct smscore_idlist_t { | ||
52 | struct list_head entry; | ||
53 | int id; | ||
54 | int data_type; | ||
55 | }; | ||
56 | |||
57 | struct smscore_client_t { | ||
58 | struct list_head entry; | ||
59 | struct smscore_device_t *coredev; | ||
60 | void *context; | ||
61 | struct list_head idlist; | ||
62 | onresponse_t onresponse_handler; | ||
63 | onremove_t onremove_handler; | ||
64 | }; | ||
65 | |||
66 | void smscore_set_board_id(struct smscore_device_t *core, int id) | ||
67 | { | ||
68 | core->board_id = id; | ||
69 | } | ||
70 | |||
71 | int smscore_led_state(struct smscore_device_t *core, int led) | ||
72 | { | ||
73 | if (led >= 0) | ||
74 | core->led_state = led; | ||
75 | return core->led_state; | ||
76 | } | ||
77 | EXPORT_SYMBOL_GPL(smscore_set_board_id); | ||
78 | |||
79 | int smscore_get_board_id(struct smscore_device_t *core) | ||
80 | { | ||
81 | return core->board_id; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(smscore_get_board_id); | ||
84 | |||
85 | struct smscore_registry_entry_t { | ||
86 | struct list_head entry; | ||
87 | char devpath[32]; | ||
88 | int mode; | ||
89 | enum sms_device_type_st type; | ||
90 | }; | ||
91 | |||
92 | static struct list_head g_smscore_notifyees; | ||
93 | static struct list_head g_smscore_devices; | ||
94 | static struct mutex g_smscore_deviceslock; | ||
95 | |||
96 | static struct list_head g_smscore_registry; | ||
97 | static struct mutex g_smscore_registrylock; | ||
98 | |||
99 | static int default_mode = 4; | ||
100 | |||
101 | module_param(default_mode, int, 0644); | ||
102 | MODULE_PARM_DESC(default_mode, "default firmware id (device mode)"); | ||
103 | |||
104 | static struct smscore_registry_entry_t *smscore_find_registry(char *devpath) | ||
105 | { | ||
106 | struct smscore_registry_entry_t *entry; | ||
107 | struct list_head *next; | ||
108 | |||
109 | kmutex_lock(&g_smscore_registrylock); | ||
110 | for (next = g_smscore_registry.next; | ||
111 | next != &g_smscore_registry; | ||
112 | next = next->next) { | ||
113 | entry = (struct smscore_registry_entry_t *) next; | ||
114 | if (!strcmp(entry->devpath, devpath)) { | ||
115 | kmutex_unlock(&g_smscore_registrylock); | ||
116 | return entry; | ||
117 | } | ||
118 | } | ||
119 | entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL); | ||
120 | if (entry) { | ||
121 | entry->mode = default_mode; | ||
122 | strcpy(entry->devpath, devpath); | ||
123 | list_add(&entry->entry, &g_smscore_registry); | ||
124 | } else | ||
125 | sms_err("failed to create smscore_registry."); | ||
126 | kmutex_unlock(&g_smscore_registrylock); | ||
127 | return entry; | ||
128 | } | ||
129 | |||
130 | int smscore_registry_getmode(char *devpath) | ||
131 | { | ||
132 | struct smscore_registry_entry_t *entry; | ||
133 | |||
134 | entry = smscore_find_registry(devpath); | ||
135 | if (entry) | ||
136 | return entry->mode; | ||
137 | else | ||
138 | sms_err("No registry found."); | ||
139 | |||
140 | return default_mode; | ||
141 | } | ||
142 | EXPORT_SYMBOL_GPL(smscore_registry_getmode); | ||
143 | |||
144 | static enum sms_device_type_st smscore_registry_gettype(char *devpath) | ||
145 | { | ||
146 | struct smscore_registry_entry_t *entry; | ||
147 | |||
148 | entry = smscore_find_registry(devpath); | ||
149 | if (entry) | ||
150 | return entry->type; | ||
151 | else | ||
152 | sms_err("No registry found."); | ||
153 | |||
154 | return -1; | ||
155 | } | ||
156 | |||
157 | void smscore_registry_setmode(char *devpath, int mode) | ||
158 | { | ||
159 | struct smscore_registry_entry_t *entry; | ||
160 | |||
161 | entry = smscore_find_registry(devpath); | ||
162 | if (entry) | ||
163 | entry->mode = mode; | ||
164 | else | ||
165 | sms_err("No registry found."); | ||
166 | } | ||
167 | |||
168 | static void smscore_registry_settype(char *devpath, | ||
169 | enum sms_device_type_st type) | ||
170 | { | ||
171 | struct smscore_registry_entry_t *entry; | ||
172 | |||
173 | entry = smscore_find_registry(devpath); | ||
174 | if (entry) | ||
175 | entry->type = type; | ||
176 | else | ||
177 | sms_err("No registry found."); | ||
178 | } | ||
179 | |||
180 | |||
181 | static void list_add_locked(struct list_head *new, struct list_head *head, | ||
182 | spinlock_t *lock) | ||
183 | { | ||
184 | unsigned long flags; | ||
185 | |||
186 | spin_lock_irqsave(lock, flags); | ||
187 | |||
188 | list_add(new, head); | ||
189 | |||
190 | spin_unlock_irqrestore(lock, flags); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * register a client callback that called when device plugged in/unplugged | ||
195 | * NOTE: if devices exist callback is called immediately for each device | ||
196 | * | ||
197 | * @param hotplug callback | ||
198 | * | ||
199 | * @return 0 on success, <0 on error. | ||
200 | */ | ||
201 | int smscore_register_hotplug(hotplug_t hotplug) | ||
202 | { | ||
203 | struct smscore_device_notifyee_t *notifyee; | ||
204 | struct list_head *next, *first; | ||
205 | int rc = 0; | ||
206 | |||
207 | kmutex_lock(&g_smscore_deviceslock); | ||
208 | |||
209 | notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t), | ||
210 | GFP_KERNEL); | ||
211 | if (notifyee) { | ||
212 | /* now notify callback about existing devices */ | ||
213 | first = &g_smscore_devices; | ||
214 | for (next = first->next; | ||
215 | next != first && !rc; | ||
216 | next = next->next) { | ||
217 | struct smscore_device_t *coredev = | ||
218 | (struct smscore_device_t *) next; | ||
219 | rc = hotplug(coredev, coredev->device, 1); | ||
220 | } | ||
221 | |||
222 | if (rc >= 0) { | ||
223 | notifyee->hotplug = hotplug; | ||
224 | list_add(¬ifyee->entry, &g_smscore_notifyees); | ||
225 | } else | ||
226 | kfree(notifyee); | ||
227 | } else | ||
228 | rc = -ENOMEM; | ||
229 | |||
230 | kmutex_unlock(&g_smscore_deviceslock); | ||
231 | |||
232 | return rc; | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(smscore_register_hotplug); | ||
235 | |||
236 | /** | ||
237 | * unregister a client callback that called when device plugged in/unplugged | ||
238 | * | ||
239 | * @param hotplug callback | ||
240 | * | ||
241 | */ | ||
242 | void smscore_unregister_hotplug(hotplug_t hotplug) | ||
243 | { | ||
244 | struct list_head *next, *first; | ||
245 | |||
246 | kmutex_lock(&g_smscore_deviceslock); | ||
247 | |||
248 | first = &g_smscore_notifyees; | ||
249 | |||
250 | for (next = first->next; next != first;) { | ||
251 | struct smscore_device_notifyee_t *notifyee = | ||
252 | (struct smscore_device_notifyee_t *) next; | ||
253 | next = next->next; | ||
254 | |||
255 | if (notifyee->hotplug == hotplug) { | ||
256 | list_del(¬ifyee->entry); | ||
257 | kfree(notifyee); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | kmutex_unlock(&g_smscore_deviceslock); | ||
262 | } | ||
263 | EXPORT_SYMBOL_GPL(smscore_unregister_hotplug); | ||
264 | |||
265 | static void smscore_notify_clients(struct smscore_device_t *coredev) | ||
266 | { | ||
267 | struct smscore_client_t *client; | ||
268 | |||
269 | /* the client must call smscore_unregister_client from remove handler */ | ||
270 | while (!list_empty(&coredev->clients)) { | ||
271 | client = (struct smscore_client_t *) coredev->clients.next; | ||
272 | client->onremove_handler(client->context); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static int smscore_notify_callbacks(struct smscore_device_t *coredev, | ||
277 | struct device *device, int arrival) | ||
278 | { | ||
279 | struct smscore_device_notifyee_t *elem; | ||
280 | int rc = 0; | ||
281 | |||
282 | /* note: must be called under g_deviceslock */ | ||
283 | |||
284 | list_for_each_entry(elem, &g_smscore_notifyees, entry) { | ||
285 | rc = elem->hotplug(coredev, device, arrival); | ||
286 | if (rc < 0) | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | return rc; | ||
291 | } | ||
292 | |||
293 | static struct | ||
294 | smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, | ||
295 | dma_addr_t common_buffer_phys) | ||
296 | { | ||
297 | struct smscore_buffer_t *cb = | ||
298 | kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL); | ||
299 | if (!cb) { | ||
300 | sms_info("kmalloc(...) failed"); | ||
301 | return NULL; | ||
302 | } | ||
303 | |||
304 | cb->p = buffer; | ||
305 | cb->offset_in_common = buffer - (u8 *) common_buffer; | ||
306 | cb->phys = common_buffer_phys + cb->offset_in_common; | ||
307 | |||
308 | return cb; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * creates coredev object for a device, prepares buffers, | ||
313 | * creates buffer mappings, notifies registered hotplugs about new device. | ||
314 | * | ||
315 | * @param params device pointer to struct with device specific parameters | ||
316 | * and handlers | ||
317 | * @param coredev pointer to a value that receives created coredev object | ||
318 | * | ||
319 | * @return 0 on success, <0 on error. | ||
320 | */ | ||
321 | int smscore_register_device(struct smsdevice_params_t *params, | ||
322 | struct smscore_device_t **coredev) | ||
323 | { | ||
324 | struct smscore_device_t *dev; | ||
325 | u8 *buffer; | ||
326 | |||
327 | dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL); | ||
328 | if (!dev) { | ||
329 | sms_info("kzalloc(...) failed"); | ||
330 | return -ENOMEM; | ||
331 | } | ||
332 | |||
333 | /* init list entry so it could be safe in smscore_unregister_device */ | ||
334 | INIT_LIST_HEAD(&dev->entry); | ||
335 | |||
336 | /* init queues */ | ||
337 | INIT_LIST_HEAD(&dev->clients); | ||
338 | INIT_LIST_HEAD(&dev->buffers); | ||
339 | |||
340 | /* init locks */ | ||
341 | spin_lock_init(&dev->clientslock); | ||
342 | spin_lock_init(&dev->bufferslock); | ||
343 | |||
344 | /* init completion events */ | ||
345 | init_completion(&dev->version_ex_done); | ||
346 | init_completion(&dev->data_download_done); | ||
347 | init_completion(&dev->trigger_done); | ||
348 | init_completion(&dev->init_device_done); | ||
349 | init_completion(&dev->reload_start_done); | ||
350 | init_completion(&dev->resume_done); | ||
351 | init_completion(&dev->gpio_configuration_done); | ||
352 | init_completion(&dev->gpio_set_level_done); | ||
353 | init_completion(&dev->gpio_get_level_done); | ||
354 | init_completion(&dev->ir_init_done); | ||
355 | |||
356 | /* Buffer management */ | ||
357 | init_waitqueue_head(&dev->buffer_mng_waitq); | ||
358 | |||
359 | /* alloc common buffer */ | ||
360 | dev->common_buffer_size = params->buffer_size * params->num_buffers; | ||
361 | dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, | ||
362 | &dev->common_buffer_phys, | ||
363 | GFP_KERNEL | GFP_DMA); | ||
364 | if (!dev->common_buffer) { | ||
365 | smscore_unregister_device(dev); | ||
366 | return -ENOMEM; | ||
367 | } | ||
368 | |||
369 | /* prepare dma buffers */ | ||
370 | for (buffer = dev->common_buffer; | ||
371 | dev->num_buffers < params->num_buffers; | ||
372 | dev->num_buffers++, buffer += params->buffer_size) { | ||
373 | struct smscore_buffer_t *cb = | ||
374 | smscore_createbuffer(buffer, dev->common_buffer, | ||
375 | dev->common_buffer_phys); | ||
376 | if (!cb) { | ||
377 | smscore_unregister_device(dev); | ||
378 | return -ENOMEM; | ||
379 | } | ||
380 | |||
381 | smscore_putbuffer(dev, cb); | ||
382 | } | ||
383 | |||
384 | sms_info("allocated %d buffers", dev->num_buffers); | ||
385 | |||
386 | dev->mode = DEVICE_MODE_NONE; | ||
387 | dev->context = params->context; | ||
388 | dev->device = params->device; | ||
389 | dev->setmode_handler = params->setmode_handler; | ||
390 | dev->detectmode_handler = params->detectmode_handler; | ||
391 | dev->sendrequest_handler = params->sendrequest_handler; | ||
392 | dev->preload_handler = params->preload_handler; | ||
393 | dev->postload_handler = params->postload_handler; | ||
394 | |||
395 | dev->device_flags = params->flags; | ||
396 | strcpy(dev->devpath, params->devpath); | ||
397 | |||
398 | smscore_registry_settype(dev->devpath, params->device_type); | ||
399 | |||
400 | /* add device to devices list */ | ||
401 | kmutex_lock(&g_smscore_deviceslock); | ||
402 | list_add(&dev->entry, &g_smscore_devices); | ||
403 | kmutex_unlock(&g_smscore_deviceslock); | ||
404 | |||
405 | *coredev = dev; | ||
406 | |||
407 | sms_info("device %p created", dev); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | EXPORT_SYMBOL_GPL(smscore_register_device); | ||
412 | |||
413 | |||
414 | static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, | ||
415 | void *buffer, size_t size, struct completion *completion) { | ||
416 | int rc = coredev->sendrequest_handler(coredev->context, buffer, size); | ||
417 | if (rc < 0) { | ||
418 | sms_info("sendrequest returned error %d", rc); | ||
419 | return rc; | ||
420 | } | ||
421 | |||
422 | return wait_for_completion_timeout(completion, | ||
423 | msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ? | ||
424 | 0 : -ETIME; | ||
425 | } | ||
426 | |||
427 | /** | ||
428 | * Starts & enables IR operations | ||
429 | * | ||
430 | * @return 0 on success, < 0 on error. | ||
431 | */ | ||
432 | static int smscore_init_ir(struct smscore_device_t *coredev) | ||
433 | { | ||
434 | int ir_io; | ||
435 | int rc; | ||
436 | void *buffer; | ||
437 | |||
438 | coredev->ir.dev = NULL; | ||
439 | ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; | ||
440 | if (ir_io) {/* only if IR port exist we use IR sub-module */ | ||
441 | sms_info("IR loading"); | ||
442 | rc = sms_ir_init(coredev); | ||
443 | |||
444 | if (rc != 0) | ||
445 | sms_err("Error initialization DTV IR sub-module"); | ||
446 | else { | ||
447 | buffer = kmalloc(sizeof(struct SmsMsgData_ST2) + | ||
448 | SMS_DMA_ALIGNMENT, | ||
449 | GFP_KERNEL | GFP_DMA); | ||
450 | if (buffer) { | ||
451 | struct SmsMsgData_ST2 *msg = | ||
452 | (struct SmsMsgData_ST2 *) | ||
453 | SMS_ALIGN_ADDRESS(buffer); | ||
454 | |||
455 | SMS_INIT_MSG(&msg->xMsgHeader, | ||
456 | MSG_SMS_START_IR_REQ, | ||
457 | sizeof(struct SmsMsgData_ST2)); | ||
458 | msg->msgData[0] = coredev->ir.controller; | ||
459 | msg->msgData[1] = coredev->ir.timeout; | ||
460 | |||
461 | smsendian_handle_tx_message( | ||
462 | (struct SmsMsgHdr_ST2 *)msg); | ||
463 | rc = smscore_sendrequest_and_wait(coredev, msg, | ||
464 | msg->xMsgHeader. msgLength, | ||
465 | &coredev->ir_init_done); | ||
466 | |||
467 | kfree(buffer); | ||
468 | } else | ||
469 | sms_err | ||
470 | ("Sending IR initialization message failed"); | ||
471 | } | ||
472 | } else | ||
473 | sms_info("IR port has not been detected"); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * sets initial device mode and notifies client hotplugs that device is ready | ||
480 | * | ||
481 | * @param coredev pointer to a coredev object returned by | ||
482 | * smscore_register_device | ||
483 | * | ||
484 | * @return 0 on success, <0 on error. | ||
485 | */ | ||
486 | int smscore_start_device(struct smscore_device_t *coredev) | ||
487 | { | ||
488 | int rc = smscore_set_device_mode( | ||
489 | coredev, smscore_registry_getmode(coredev->devpath)); | ||
490 | if (rc < 0) { | ||
491 | sms_info("set device mode faile , rc %d", rc); | ||
492 | return rc; | ||
493 | } | ||
494 | |||
495 | kmutex_lock(&g_smscore_deviceslock); | ||
496 | |||
497 | rc = smscore_notify_callbacks(coredev, coredev->device, 1); | ||
498 | smscore_init_ir(coredev); | ||
499 | |||
500 | sms_info("device %p started, rc %d", coredev, rc); | ||
501 | |||
502 | kmutex_unlock(&g_smscore_deviceslock); | ||
503 | |||
504 | return rc; | ||
505 | } | ||
506 | EXPORT_SYMBOL_GPL(smscore_start_device); | ||
507 | |||
508 | |||
509 | static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | ||
510 | void *buffer, size_t size) | ||
511 | { | ||
512 | struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; | ||
513 | struct SmsMsgHdr_ST *msg; | ||
514 | u32 mem_address; | ||
515 | u8 *payload = firmware->Payload; | ||
516 | int rc = 0; | ||
517 | firmware->StartAddress = le32_to_cpu(firmware->StartAddress); | ||
518 | firmware->Length = le32_to_cpu(firmware->Length); | ||
519 | |||
520 | mem_address = firmware->StartAddress; | ||
521 | |||
522 | sms_info("loading FW to addr 0x%x size %d", | ||
523 | mem_address, firmware->Length); | ||
524 | if (coredev->preload_handler) { | ||
525 | rc = coredev->preload_handler(coredev->context); | ||
526 | if (rc < 0) | ||
527 | return rc; | ||
528 | } | ||
529 | |||
530 | /* PAGE_SIZE buffer shall be enough and dma aligned */ | ||
531 | msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); | ||
532 | if (!msg) | ||
533 | return -ENOMEM; | ||
534 | |||
535 | if (coredev->mode != DEVICE_MODE_NONE) { | ||
536 | sms_debug("sending reload command."); | ||
537 | SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ, | ||
538 | sizeof(struct SmsMsgHdr_ST)); | ||
539 | rc = smscore_sendrequest_and_wait(coredev, msg, | ||
540 | msg->msgLength, | ||
541 | &coredev->reload_start_done); | ||
542 | mem_address = *(u32 *) &payload[20]; | ||
543 | } | ||
544 | |||
545 | while (size && rc >= 0) { | ||
546 | struct SmsDataDownload_ST *DataMsg = | ||
547 | (struct SmsDataDownload_ST *) msg; | ||
548 | int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE); | ||
549 | |||
550 | SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ, | ||
551 | (u16)(sizeof(struct SmsMsgHdr_ST) + | ||
552 | sizeof(u32) + payload_size)); | ||
553 | |||
554 | DataMsg->MemAddr = mem_address; | ||
555 | memcpy(DataMsg->Payload, payload, payload_size); | ||
556 | |||
557 | if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) && | ||
558 | (coredev->mode == DEVICE_MODE_NONE)) | ||
559 | rc = coredev->sendrequest_handler( | ||
560 | coredev->context, DataMsg, | ||
561 | DataMsg->xMsgHeader.msgLength); | ||
562 | else | ||
563 | rc = smscore_sendrequest_and_wait( | ||
564 | coredev, DataMsg, | ||
565 | DataMsg->xMsgHeader.msgLength, | ||
566 | &coredev->data_download_done); | ||
567 | |||
568 | payload += payload_size; | ||
569 | size -= payload_size; | ||
570 | mem_address += payload_size; | ||
571 | } | ||
572 | |||
573 | if (rc >= 0) { | ||
574 | if (coredev->mode == DEVICE_MODE_NONE) { | ||
575 | struct SmsMsgData_ST *TriggerMsg = | ||
576 | (struct SmsMsgData_ST *) msg; | ||
577 | |||
578 | SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, | ||
579 | sizeof(struct SmsMsgHdr_ST) + | ||
580 | sizeof(u32) * 5); | ||
581 | |||
582 | TriggerMsg->msgData[0] = firmware->StartAddress; | ||
583 | /* Entry point */ | ||
584 | TriggerMsg->msgData[1] = 5; /* Priority */ | ||
585 | TriggerMsg->msgData[2] = 0x200; /* Stack size */ | ||
586 | TriggerMsg->msgData[3] = 0; /* Parameter */ | ||
587 | TriggerMsg->msgData[4] = 4; /* Task ID */ | ||
588 | |||
589 | if (coredev->device_flags & SMS_ROM_NO_RESPONSE) { | ||
590 | rc = coredev->sendrequest_handler( | ||
591 | coredev->context, TriggerMsg, | ||
592 | TriggerMsg->xMsgHeader.msgLength); | ||
593 | msleep(100); | ||
594 | } else | ||
595 | rc = smscore_sendrequest_and_wait( | ||
596 | coredev, TriggerMsg, | ||
597 | TriggerMsg->xMsgHeader.msgLength, | ||
598 | &coredev->trigger_done); | ||
599 | } else { | ||
600 | SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ, | ||
601 | sizeof(struct SmsMsgHdr_ST)); | ||
602 | |||
603 | rc = coredev->sendrequest_handler(coredev->context, | ||
604 | msg, msg->msgLength); | ||
605 | } | ||
606 | msleep(500); | ||
607 | } | ||
608 | |||
609 | sms_debug("rc=%d, postload=%p ", rc, | ||
610 | coredev->postload_handler); | ||
611 | |||
612 | kfree(msg); | ||
613 | |||
614 | return ((rc >= 0) && coredev->postload_handler) ? | ||
615 | coredev->postload_handler(coredev->context) : | ||
616 | rc; | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * loads specified firmware into a buffer and calls device loadfirmware_handler | ||
621 | * | ||
622 | * @param coredev pointer to a coredev object returned by | ||
623 | * smscore_register_device | ||
624 | * @param filename null-terminated string specifies firmware file name | ||
625 | * @param loadfirmware_handler device handler that loads firmware | ||
626 | * | ||
627 | * @return 0 on success, <0 on error. | ||
628 | */ | ||
629 | static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, | ||
630 | char *filename, | ||
631 | loadfirmware_t loadfirmware_handler) | ||
632 | { | ||
633 | int rc = -ENOENT; | ||
634 | const struct firmware *fw; | ||
635 | u8 *fw_buffer; | ||
636 | |||
637 | if (loadfirmware_handler == NULL && !(coredev->device_flags & | ||
638 | SMS_DEVICE_FAMILY2)) | ||
639 | return -EINVAL; | ||
640 | |||
641 | rc = request_firmware(&fw, filename, coredev->device); | ||
642 | if (rc < 0) { | ||
643 | sms_info("failed to open \"%s\"", filename); | ||
644 | return rc; | ||
645 | } | ||
646 | sms_info("read FW %s, size=%zd", filename, fw->size); | ||
647 | fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), | ||
648 | GFP_KERNEL | GFP_DMA); | ||
649 | if (fw_buffer) { | ||
650 | memcpy(fw_buffer, fw->data, fw->size); | ||
651 | |||
652 | rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? | ||
653 | smscore_load_firmware_family2(coredev, | ||
654 | fw_buffer, | ||
655 | fw->size) : | ||
656 | loadfirmware_handler(coredev->context, | ||
657 | fw_buffer, fw->size); | ||
658 | |||
659 | kfree(fw_buffer); | ||
660 | } else { | ||
661 | sms_info("failed to allocate firmware buffer"); | ||
662 | rc = -ENOMEM; | ||
663 | } | ||
664 | |||
665 | release_firmware(fw); | ||
666 | |||
667 | return rc; | ||
668 | } | ||
669 | |||
670 | /** | ||
671 | * notifies all clients registered with the device, notifies hotplugs, | ||
672 | * frees all buffers and coredev object | ||
673 | * | ||
674 | * @param coredev pointer to a coredev object returned by | ||
675 | * smscore_register_device | ||
676 | * | ||
677 | * @return 0 on success, <0 on error. | ||
678 | */ | ||
679 | void smscore_unregister_device(struct smscore_device_t *coredev) | ||
680 | { | ||
681 | struct smscore_buffer_t *cb; | ||
682 | int num_buffers = 0; | ||
683 | int retry = 0; | ||
684 | |||
685 | kmutex_lock(&g_smscore_deviceslock); | ||
686 | |||
687 | /* Release input device (IR) resources */ | ||
688 | sms_ir_exit(coredev); | ||
689 | |||
690 | smscore_notify_clients(coredev); | ||
691 | smscore_notify_callbacks(coredev, NULL, 0); | ||
692 | |||
693 | /* at this point all buffers should be back | ||
694 | * onresponse must no longer be called */ | ||
695 | |||
696 | while (1) { | ||
697 | while (!list_empty(&coredev->buffers)) { | ||
698 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
699 | list_del(&cb->entry); | ||
700 | kfree(cb); | ||
701 | num_buffers++; | ||
702 | } | ||
703 | if (num_buffers == coredev->num_buffers) | ||
704 | break; | ||
705 | if (++retry > 10) { | ||
706 | sms_info("exiting although " | ||
707 | "not all buffers released."); | ||
708 | break; | ||
709 | } | ||
710 | |||
711 | sms_info("waiting for %d buffer(s)", | ||
712 | coredev->num_buffers - num_buffers); | ||
713 | msleep(100); | ||
714 | } | ||
715 | |||
716 | sms_info("freed %d buffers", num_buffers); | ||
717 | |||
718 | if (coredev->common_buffer) | ||
719 | dma_free_coherent(NULL, coredev->common_buffer_size, | ||
720 | coredev->common_buffer, coredev->common_buffer_phys); | ||
721 | |||
722 | if (coredev->fw_buf != NULL) | ||
723 | kfree(coredev->fw_buf); | ||
724 | |||
725 | list_del(&coredev->entry); | ||
726 | kfree(coredev); | ||
727 | |||
728 | kmutex_unlock(&g_smscore_deviceslock); | ||
729 | |||
730 | sms_info("device %p destroyed", coredev); | ||
731 | } | ||
732 | EXPORT_SYMBOL_GPL(smscore_unregister_device); | ||
733 | |||
734 | static int smscore_detect_mode(struct smscore_device_t *coredev) | ||
735 | { | ||
736 | void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT, | ||
737 | GFP_KERNEL | GFP_DMA); | ||
738 | struct SmsMsgHdr_ST *msg = | ||
739 | (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer); | ||
740 | int rc; | ||
741 | |||
742 | if (!buffer) | ||
743 | return -ENOMEM; | ||
744 | |||
745 | SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ, | ||
746 | sizeof(struct SmsMsgHdr_ST)); | ||
747 | |||
748 | rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, | ||
749 | &coredev->version_ex_done); | ||
750 | if (rc == -ETIME) { | ||
751 | sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try"); | ||
752 | |||
753 | if (wait_for_completion_timeout(&coredev->resume_done, | ||
754 | msecs_to_jiffies(5000))) { | ||
755 | rc = smscore_sendrequest_and_wait( | ||
756 | coredev, msg, msg->msgLength, | ||
757 | &coredev->version_ex_done); | ||
758 | if (rc < 0) | ||
759 | sms_err("MSG_SMS_GET_VERSION_EX_REQ failed " | ||
760 | "second try, rc %d", rc); | ||
761 | } else | ||
762 | rc = -ETIME; | ||
763 | } | ||
764 | |||
765 | kfree(buffer); | ||
766 | |||
767 | return rc; | ||
768 | } | ||
769 | |||
770 | static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { | ||
771 | /*Stellar NOVA A0 Nova B0 VEGA*/ | ||
772 | /*DVBT*/ | ||
773 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | ||
774 | /*DVBH*/ | ||
775 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | ||
776 | /*TDMB*/ | ||
777 | {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"}, | ||
778 | /*DABIP*/ | ||
779 | {"none", "none", "none", "none"}, | ||
780 | /*BDA*/ | ||
781 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | ||
782 | /*ISDBT*/ | ||
783 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | ||
784 | /*ISDBTBDA*/ | ||
785 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | ||
786 | /*CMMB*/ | ||
787 | {"none", "none", "none", "cmmb_vega_12mhz.inp"} | ||
788 | }; | ||
789 | |||
790 | static inline char *sms_get_fw_name(struct smscore_device_t *coredev, | ||
791 | int mode, enum sms_device_type_st type) | ||
792 | { | ||
793 | char **fw = sms_get_board(smscore_get_board_id(coredev))->fw; | ||
794 | return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type]; | ||
795 | } | ||
796 | |||
797 | /** | ||
798 | * calls device handler to change mode of operation | ||
799 | * NOTE: stellar/usb may disconnect when changing mode | ||
800 | * | ||
801 | * @param coredev pointer to a coredev object returned by | ||
802 | * smscore_register_device | ||
803 | * @param mode requested mode of operation | ||
804 | * | ||
805 | * @return 0 on success, <0 on error. | ||
806 | */ | ||
807 | int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) | ||
808 | { | ||
809 | void *buffer; | ||
810 | int rc = 0; | ||
811 | enum sms_device_type_st type; | ||
812 | |||
813 | sms_debug("set device mode to %d", mode); | ||
814 | if (coredev->device_flags & SMS_DEVICE_FAMILY2) { | ||
815 | if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) { | ||
816 | sms_err("invalid mode specified %d", mode); | ||
817 | return -EINVAL; | ||
818 | } | ||
819 | |||
820 | smscore_registry_setmode(coredev->devpath, mode); | ||
821 | |||
822 | if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) { | ||
823 | rc = smscore_detect_mode(coredev); | ||
824 | if (rc < 0) { | ||
825 | sms_err("mode detect failed %d", rc); | ||
826 | return rc; | ||
827 | } | ||
828 | } | ||
829 | |||
830 | if (coredev->mode == mode) { | ||
831 | sms_info("device mode %d already set", mode); | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | if (!(coredev->modes_supported & (1 << mode))) { | ||
836 | char *fw_filename; | ||
837 | |||
838 | type = smscore_registry_gettype(coredev->devpath); | ||
839 | fw_filename = sms_get_fw_name(coredev, mode, type); | ||
840 | |||
841 | rc = smscore_load_firmware_from_file(coredev, | ||
842 | fw_filename, NULL); | ||
843 | if (rc < 0) { | ||
844 | sms_warn("error %d loading firmware: %s, " | ||
845 | "trying again with default firmware", | ||
846 | rc, fw_filename); | ||
847 | |||
848 | /* try again with the default firmware */ | ||
849 | fw_filename = smscore_fw_lkup[mode][type]; | ||
850 | rc = smscore_load_firmware_from_file(coredev, | ||
851 | fw_filename, NULL); | ||
852 | |||
853 | if (rc < 0) { | ||
854 | sms_warn("error %d loading " | ||
855 | "firmware: %s", rc, | ||
856 | fw_filename); | ||
857 | return rc; | ||
858 | } | ||
859 | } | ||
860 | sms_log("firmware download success: %s", fw_filename); | ||
861 | } else | ||
862 | sms_info("mode %d supported by running " | ||
863 | "firmware", mode); | ||
864 | |||
865 | buffer = kmalloc(sizeof(struct SmsMsgData_ST) + | ||
866 | SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); | ||
867 | if (buffer) { | ||
868 | struct SmsMsgData_ST *msg = | ||
869 | (struct SmsMsgData_ST *) | ||
870 | SMS_ALIGN_ADDRESS(buffer); | ||
871 | |||
872 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, | ||
873 | sizeof(struct SmsMsgData_ST)); | ||
874 | msg->msgData[0] = mode; | ||
875 | |||
876 | rc = smscore_sendrequest_and_wait( | ||
877 | coredev, msg, msg->xMsgHeader.msgLength, | ||
878 | &coredev->init_device_done); | ||
879 | |||
880 | kfree(buffer); | ||
881 | } else { | ||
882 | sms_err("Could not allocate buffer for " | ||
883 | "init device message."); | ||
884 | rc = -ENOMEM; | ||
885 | } | ||
886 | } else { | ||
887 | if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { | ||
888 | sms_err("invalid mode specified %d", mode); | ||
889 | return -EINVAL; | ||
890 | } | ||
891 | |||
892 | smscore_registry_setmode(coredev->devpath, mode); | ||
893 | |||
894 | if (coredev->detectmode_handler) | ||
895 | coredev->detectmode_handler(coredev->context, | ||
896 | &coredev->mode); | ||
897 | |||
898 | if (coredev->mode != mode && coredev->setmode_handler) | ||
899 | rc = coredev->setmode_handler(coredev->context, mode); | ||
900 | } | ||
901 | |||
902 | if (rc >= 0) { | ||
903 | coredev->mode = mode; | ||
904 | coredev->device_flags &= ~SMS_DEVICE_NOT_READY; | ||
905 | } | ||
906 | |||
907 | if (rc < 0) | ||
908 | sms_err("return error code %d.", rc); | ||
909 | return rc; | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * calls device handler to get current mode of operation | ||
914 | * | ||
915 | * @param coredev pointer to a coredev object returned by | ||
916 | * smscore_register_device | ||
917 | * | ||
918 | * @return current mode | ||
919 | */ | ||
920 | int smscore_get_device_mode(struct smscore_device_t *coredev) | ||
921 | { | ||
922 | return coredev->mode; | ||
923 | } | ||
924 | EXPORT_SYMBOL_GPL(smscore_get_device_mode); | ||
925 | |||
926 | /** | ||
927 | * find client by response id & type within the clients list. | ||
928 | * return client handle or NULL. | ||
929 | * | ||
930 | * @param coredev pointer to a coredev object returned by | ||
931 | * smscore_register_device | ||
932 | * @param data_type client data type (SMS_DONT_CARE for all types) | ||
933 | * @param id client id (SMS_DONT_CARE for all id) | ||
934 | * | ||
935 | */ | ||
936 | static struct | ||
937 | smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, | ||
938 | int data_type, int id) | ||
939 | { | ||
940 | struct list_head *first; | ||
941 | struct smscore_client_t *client; | ||
942 | unsigned long flags; | ||
943 | struct list_head *firstid; | ||
944 | struct smscore_idlist_t *client_id; | ||
945 | |||
946 | spin_lock_irqsave(&coredev->clientslock, flags); | ||
947 | first = &coredev->clients; | ||
948 | list_for_each_entry(client, first, entry) { | ||
949 | firstid = &client->idlist; | ||
950 | list_for_each_entry(client_id, firstid, entry) { | ||
951 | if ((client_id->id == id) && | ||
952 | (client_id->data_type == data_type || | ||
953 | (client_id->data_type == 0))) | ||
954 | goto found; | ||
955 | } | ||
956 | } | ||
957 | client = NULL; | ||
958 | found: | ||
959 | spin_unlock_irqrestore(&coredev->clientslock, flags); | ||
960 | return client; | ||
961 | } | ||
962 | |||
963 | /** | ||
964 | * find client by response id/type, call clients onresponse handler | ||
965 | * return buffer to pool on error | ||
966 | * | ||
967 | * @param coredev pointer to a coredev object returned by | ||
968 | * smscore_register_device | ||
969 | * @param cb pointer to response buffer descriptor | ||
970 | * | ||
971 | */ | ||
972 | void smscore_onresponse(struct smscore_device_t *coredev, | ||
973 | struct smscore_buffer_t *cb) { | ||
974 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p | ||
975 | + cb->offset); | ||
976 | struct smscore_client_t *client; | ||
977 | int rc = -EBUSY; | ||
978 | static unsigned long last_sample_time; /* = 0; */ | ||
979 | static int data_total; /* = 0; */ | ||
980 | unsigned long time_now = jiffies_to_msecs(jiffies); | ||
981 | |||
982 | if (!last_sample_time) | ||
983 | last_sample_time = time_now; | ||
984 | |||
985 | if (time_now - last_sample_time > 10000) { | ||
986 | sms_debug("\ndata rate %d bytes/secs", | ||
987 | (int)((data_total * 1000) / | ||
988 | (time_now - last_sample_time))); | ||
989 | |||
990 | last_sample_time = time_now; | ||
991 | data_total = 0; | ||
992 | } | ||
993 | |||
994 | data_total += cb->size; | ||
995 | /* Do we need to re-route? */ | ||
996 | if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) || | ||
997 | (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) { | ||
998 | if (coredev->mode == DEVICE_MODE_DVBT_BDA) | ||
999 | phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID; | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); | ||
1004 | |||
1005 | /* If no client registered for type & id, | ||
1006 | * check for control client where type is not registered */ | ||
1007 | if (client) | ||
1008 | rc = client->onresponse_handler(client->context, cb); | ||
1009 | |||
1010 | if (rc < 0) { | ||
1011 | switch (phdr->msgType) { | ||
1012 | case MSG_SMS_GET_VERSION_EX_RES: | ||
1013 | { | ||
1014 | struct SmsVersionRes_ST *ver = | ||
1015 | (struct SmsVersionRes_ST *) phdr; | ||
1016 | sms_debug("MSG_SMS_GET_VERSION_EX_RES " | ||
1017 | "id %d prots 0x%x ver %d.%d", | ||
1018 | ver->FirmwareId, ver->SupportedProtocols, | ||
1019 | ver->RomVersionMajor, ver->RomVersionMinor); | ||
1020 | |||
1021 | coredev->mode = ver->FirmwareId == 255 ? | ||
1022 | DEVICE_MODE_NONE : ver->FirmwareId; | ||
1023 | coredev->modes_supported = ver->SupportedProtocols; | ||
1024 | |||
1025 | complete(&coredev->version_ex_done); | ||
1026 | break; | ||
1027 | } | ||
1028 | case MSG_SMS_INIT_DEVICE_RES: | ||
1029 | sms_debug("MSG_SMS_INIT_DEVICE_RES"); | ||
1030 | complete(&coredev->init_device_done); | ||
1031 | break; | ||
1032 | case MSG_SW_RELOAD_START_RES: | ||
1033 | sms_debug("MSG_SW_RELOAD_START_RES"); | ||
1034 | complete(&coredev->reload_start_done); | ||
1035 | break; | ||
1036 | case MSG_SMS_DATA_DOWNLOAD_RES: | ||
1037 | complete(&coredev->data_download_done); | ||
1038 | break; | ||
1039 | case MSG_SW_RELOAD_EXEC_RES: | ||
1040 | sms_debug("MSG_SW_RELOAD_EXEC_RES"); | ||
1041 | break; | ||
1042 | case MSG_SMS_SWDOWNLOAD_TRIGGER_RES: | ||
1043 | sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES"); | ||
1044 | complete(&coredev->trigger_done); | ||
1045 | break; | ||
1046 | case MSG_SMS_SLEEP_RESUME_COMP_IND: | ||
1047 | complete(&coredev->resume_done); | ||
1048 | break; | ||
1049 | case MSG_SMS_GPIO_CONFIG_EX_RES: | ||
1050 | sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES"); | ||
1051 | complete(&coredev->gpio_configuration_done); | ||
1052 | break; | ||
1053 | case MSG_SMS_GPIO_SET_LEVEL_RES: | ||
1054 | sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES"); | ||
1055 | complete(&coredev->gpio_set_level_done); | ||
1056 | break; | ||
1057 | case MSG_SMS_GPIO_GET_LEVEL_RES: | ||
1058 | { | ||
1059 | u32 *msgdata = (u32 *) phdr; | ||
1060 | coredev->gpio_get_res = msgdata[1]; | ||
1061 | sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d", | ||
1062 | coredev->gpio_get_res); | ||
1063 | complete(&coredev->gpio_get_level_done); | ||
1064 | break; | ||
1065 | } | ||
1066 | case MSG_SMS_START_IR_RES: | ||
1067 | complete(&coredev->ir_init_done); | ||
1068 | break; | ||
1069 | case MSG_SMS_IR_SAMPLES_IND: | ||
1070 | sms_ir_event(coredev, | ||
1071 | (const char *) | ||
1072 | ((char *)phdr | ||
1073 | + sizeof(struct SmsMsgHdr_ST)), | ||
1074 | (int)phdr->msgLength | ||
1075 | - sizeof(struct SmsMsgHdr_ST)); | ||
1076 | break; | ||
1077 | |||
1078 | default: | ||
1079 | break; | ||
1080 | } | ||
1081 | smscore_putbuffer(coredev, cb); | ||
1082 | } | ||
1083 | } | ||
1084 | EXPORT_SYMBOL_GPL(smscore_onresponse); | ||
1085 | |||
1086 | /** | ||
1087 | * return pointer to next free buffer descriptor from core pool | ||
1088 | * | ||
1089 | * @param coredev pointer to a coredev object returned by | ||
1090 | * smscore_register_device | ||
1091 | * | ||
1092 | * @return pointer to descriptor on success, NULL on error. | ||
1093 | */ | ||
1094 | |||
1095 | static struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev) | ||
1096 | { | ||
1097 | struct smscore_buffer_t *cb = NULL; | ||
1098 | unsigned long flags; | ||
1099 | |||
1100 | spin_lock_irqsave(&coredev->bufferslock, flags); | ||
1101 | if (!list_empty(&coredev->buffers)) { | ||
1102 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
1103 | list_del(&cb->entry); | ||
1104 | } | ||
1105 | spin_unlock_irqrestore(&coredev->bufferslock, flags); | ||
1106 | return cb; | ||
1107 | } | ||
1108 | |||
1109 | struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) | ||
1110 | { | ||
1111 | struct smscore_buffer_t *cb = NULL; | ||
1112 | |||
1113 | wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev))); | ||
1114 | |||
1115 | return cb; | ||
1116 | } | ||
1117 | EXPORT_SYMBOL_GPL(smscore_getbuffer); | ||
1118 | |||
1119 | /** | ||
1120 | * return buffer descriptor to a pool | ||
1121 | * | ||
1122 | * @param coredev pointer to a coredev object returned by | ||
1123 | * smscore_register_device | ||
1124 | * @param cb pointer buffer descriptor | ||
1125 | * | ||
1126 | */ | ||
1127 | void smscore_putbuffer(struct smscore_device_t *coredev, | ||
1128 | struct smscore_buffer_t *cb) { | ||
1129 | wake_up_interruptible(&coredev->buffer_mng_waitq); | ||
1130 | list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); | ||
1131 | } | ||
1132 | EXPORT_SYMBOL_GPL(smscore_putbuffer); | ||
1133 | |||
1134 | static int smscore_validate_client(struct smscore_device_t *coredev, | ||
1135 | struct smscore_client_t *client, | ||
1136 | int data_type, int id) | ||
1137 | { | ||
1138 | struct smscore_idlist_t *listentry; | ||
1139 | struct smscore_client_t *registered_client; | ||
1140 | |||
1141 | if (!client) { | ||
1142 | sms_err("bad parameter."); | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | registered_client = smscore_find_client(coredev, data_type, id); | ||
1146 | if (registered_client == client) | ||
1147 | return 0; | ||
1148 | |||
1149 | if (registered_client) { | ||
1150 | sms_err("The msg ID already registered to another client."); | ||
1151 | return -EEXIST; | ||
1152 | } | ||
1153 | listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL); | ||
1154 | if (!listentry) { | ||
1155 | sms_err("Can't allocate memory for client id."); | ||
1156 | return -ENOMEM; | ||
1157 | } | ||
1158 | listentry->id = id; | ||
1159 | listentry->data_type = data_type; | ||
1160 | list_add_locked(&listentry->entry, &client->idlist, | ||
1161 | &coredev->clientslock); | ||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | /** | ||
1166 | * creates smsclient object, check that id is taken by another client | ||
1167 | * | ||
1168 | * @param coredev pointer to a coredev object from clients hotplug | ||
1169 | * @param initial_id all messages with this id would be sent to this client | ||
1170 | * @param data_type all messages of this type would be sent to this client | ||
1171 | * @param onresponse_handler client handler that is called to | ||
1172 | * process incoming messages | ||
1173 | * @param onremove_handler client handler that is called when device is removed | ||
1174 | * @param context client-specific context | ||
1175 | * @param client pointer to a value that receives created smsclient object | ||
1176 | * | ||
1177 | * @return 0 on success, <0 on error. | ||
1178 | */ | ||
1179 | int smscore_register_client(struct smscore_device_t *coredev, | ||
1180 | struct smsclient_params_t *params, | ||
1181 | struct smscore_client_t **client) | ||
1182 | { | ||
1183 | struct smscore_client_t *newclient; | ||
1184 | /* check that no other channel with same parameters exists */ | ||
1185 | if (smscore_find_client(coredev, params->data_type, | ||
1186 | params->initial_id)) { | ||
1187 | sms_err("Client already exist."); | ||
1188 | return -EEXIST; | ||
1189 | } | ||
1190 | |||
1191 | newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL); | ||
1192 | if (!newclient) { | ||
1193 | sms_err("Failed to allocate memory for client."); | ||
1194 | return -ENOMEM; | ||
1195 | } | ||
1196 | |||
1197 | INIT_LIST_HEAD(&newclient->idlist); | ||
1198 | newclient->coredev = coredev; | ||
1199 | newclient->onresponse_handler = params->onresponse_handler; | ||
1200 | newclient->onremove_handler = params->onremove_handler; | ||
1201 | newclient->context = params->context; | ||
1202 | list_add_locked(&newclient->entry, &coredev->clients, | ||
1203 | &coredev->clientslock); | ||
1204 | smscore_validate_client(coredev, newclient, params->data_type, | ||
1205 | params->initial_id); | ||
1206 | *client = newclient; | ||
1207 | sms_debug("%p %d %d", params->context, params->data_type, | ||
1208 | params->initial_id); | ||
1209 | |||
1210 | return 0; | ||
1211 | } | ||
1212 | EXPORT_SYMBOL_GPL(smscore_register_client); | ||
1213 | |||
1214 | /** | ||
1215 | * frees smsclient object and all subclients associated with it | ||
1216 | * | ||
1217 | * @param client pointer to smsclient object returned by | ||
1218 | * smscore_register_client | ||
1219 | * | ||
1220 | */ | ||
1221 | void smscore_unregister_client(struct smscore_client_t *client) | ||
1222 | { | ||
1223 | struct smscore_device_t *coredev = client->coredev; | ||
1224 | unsigned long flags; | ||
1225 | |||
1226 | spin_lock_irqsave(&coredev->clientslock, flags); | ||
1227 | |||
1228 | |||
1229 | while (!list_empty(&client->idlist)) { | ||
1230 | struct smscore_idlist_t *identry = | ||
1231 | (struct smscore_idlist_t *) client->idlist.next; | ||
1232 | list_del(&identry->entry); | ||
1233 | kfree(identry); | ||
1234 | } | ||
1235 | |||
1236 | sms_info("%p", client->context); | ||
1237 | |||
1238 | list_del(&client->entry); | ||
1239 | kfree(client); | ||
1240 | |||
1241 | spin_unlock_irqrestore(&coredev->clientslock, flags); | ||
1242 | } | ||
1243 | EXPORT_SYMBOL_GPL(smscore_unregister_client); | ||
1244 | |||
1245 | /** | ||
1246 | * verifies that source id is not taken by another client, | ||
1247 | * calls device handler to send requests to the device | ||
1248 | * | ||
1249 | * @param client pointer to smsclient object returned by | ||
1250 | * smscore_register_client | ||
1251 | * @param buffer pointer to a request buffer | ||
1252 | * @param size size (in bytes) of request buffer | ||
1253 | * | ||
1254 | * @return 0 on success, <0 on error. | ||
1255 | */ | ||
1256 | int smsclient_sendrequest(struct smscore_client_t *client, | ||
1257 | void *buffer, size_t size) | ||
1258 | { | ||
1259 | struct smscore_device_t *coredev; | ||
1260 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer; | ||
1261 | int rc; | ||
1262 | |||
1263 | if (client == NULL) { | ||
1264 | sms_err("Got NULL client"); | ||
1265 | return -EINVAL; | ||
1266 | } | ||
1267 | |||
1268 | coredev = client->coredev; | ||
1269 | |||
1270 | /* check that no other channel with same id exists */ | ||
1271 | if (coredev == NULL) { | ||
1272 | sms_err("Got NULL coredev"); | ||
1273 | return -EINVAL; | ||
1274 | } | ||
1275 | |||
1276 | rc = smscore_validate_client(client->coredev, client, 0, | ||
1277 | phdr->msgSrcId); | ||
1278 | if (rc < 0) | ||
1279 | return rc; | ||
1280 | |||
1281 | return coredev->sendrequest_handler(coredev->context, buffer, size); | ||
1282 | } | ||
1283 | EXPORT_SYMBOL_GPL(smsclient_sendrequest); | ||
1284 | |||
1285 | |||
1286 | /* old GPIO managements implementation */ | ||
1287 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, | ||
1288 | struct smscore_config_gpio *pinconfig) | ||
1289 | { | ||
1290 | struct { | ||
1291 | struct SmsMsgHdr_ST hdr; | ||
1292 | u32 data[6]; | ||
1293 | } msg; | ||
1294 | |||
1295 | if (coredev->device_flags & SMS_DEVICE_FAMILY2) { | ||
1296 | msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1297 | msg.hdr.msgDstId = HIF_TASK; | ||
1298 | msg.hdr.msgFlags = 0; | ||
1299 | msg.hdr.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; | ||
1300 | msg.hdr.msgLength = sizeof(msg); | ||
1301 | |||
1302 | msg.data[0] = pin; | ||
1303 | msg.data[1] = pinconfig->pullupdown; | ||
1304 | |||
1305 | /* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */ | ||
1306 | msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0; | ||
1307 | |||
1308 | switch (pinconfig->outputdriving) { | ||
1309 | case SMS_GPIO_OUTPUTDRIVING_16mA: | ||
1310 | msg.data[3] = 7; /* Nova - 16mA */ | ||
1311 | break; | ||
1312 | case SMS_GPIO_OUTPUTDRIVING_12mA: | ||
1313 | msg.data[3] = 5; /* Nova - 11mA */ | ||
1314 | break; | ||
1315 | case SMS_GPIO_OUTPUTDRIVING_8mA: | ||
1316 | msg.data[3] = 3; /* Nova - 7mA */ | ||
1317 | break; | ||
1318 | case SMS_GPIO_OUTPUTDRIVING_4mA: | ||
1319 | default: | ||
1320 | msg.data[3] = 2; /* Nova - 4mA */ | ||
1321 | break; | ||
1322 | } | ||
1323 | |||
1324 | msg.data[4] = pinconfig->direction; | ||
1325 | msg.data[5] = 0; | ||
1326 | } else /* TODO: SMS_DEVICE_FAMILY1 */ | ||
1327 | return -EINVAL; | ||
1328 | |||
1329 | return coredev->sendrequest_handler(coredev->context, | ||
1330 | &msg, sizeof(msg)); | ||
1331 | } | ||
1332 | |||
1333 | int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level) | ||
1334 | { | ||
1335 | struct { | ||
1336 | struct SmsMsgHdr_ST hdr; | ||
1337 | u32 data[3]; | ||
1338 | } msg; | ||
1339 | |||
1340 | if (pin > MAX_GPIO_PIN_NUMBER) | ||
1341 | return -EINVAL; | ||
1342 | |||
1343 | msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1344 | msg.hdr.msgDstId = HIF_TASK; | ||
1345 | msg.hdr.msgFlags = 0; | ||
1346 | msg.hdr.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; | ||
1347 | msg.hdr.msgLength = sizeof(msg); | ||
1348 | |||
1349 | msg.data[0] = pin; | ||
1350 | msg.data[1] = level ? 1 : 0; | ||
1351 | msg.data[2] = 0; | ||
1352 | |||
1353 | return coredev->sendrequest_handler(coredev->context, | ||
1354 | &msg, sizeof(msg)); | ||
1355 | } | ||
1356 | |||
1357 | /* new GPIO management implementation */ | ||
1358 | static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum, | ||
1359 | u32 *pGroupNum, u32 *pGroupCfg) { | ||
1360 | |||
1361 | *pGroupCfg = 1; | ||
1362 | |||
1363 | if (PinNum <= 1) { | ||
1364 | *pTranslatedPinNum = 0; | ||
1365 | *pGroupNum = 9; | ||
1366 | *pGroupCfg = 2; | ||
1367 | } else if (PinNum >= 2 && PinNum <= 6) { | ||
1368 | *pTranslatedPinNum = 2; | ||
1369 | *pGroupNum = 0; | ||
1370 | *pGroupCfg = 2; | ||
1371 | } else if (PinNum >= 7 && PinNum <= 11) { | ||
1372 | *pTranslatedPinNum = 7; | ||
1373 | *pGroupNum = 1; | ||
1374 | } else if (PinNum >= 12 && PinNum <= 15) { | ||
1375 | *pTranslatedPinNum = 12; | ||
1376 | *pGroupNum = 2; | ||
1377 | *pGroupCfg = 3; | ||
1378 | } else if (PinNum == 16) { | ||
1379 | *pTranslatedPinNum = 16; | ||
1380 | *pGroupNum = 23; | ||
1381 | } else if (PinNum >= 17 && PinNum <= 24) { | ||
1382 | *pTranslatedPinNum = 17; | ||
1383 | *pGroupNum = 3; | ||
1384 | } else if (PinNum == 25) { | ||
1385 | *pTranslatedPinNum = 25; | ||
1386 | *pGroupNum = 6; | ||
1387 | } else if (PinNum >= 26 && PinNum <= 28) { | ||
1388 | *pTranslatedPinNum = 26; | ||
1389 | *pGroupNum = 4; | ||
1390 | } else if (PinNum == 29) { | ||
1391 | *pTranslatedPinNum = 29; | ||
1392 | *pGroupNum = 5; | ||
1393 | *pGroupCfg = 2; | ||
1394 | } else if (PinNum == 30) { | ||
1395 | *pTranslatedPinNum = 30; | ||
1396 | *pGroupNum = 8; | ||
1397 | } else if (PinNum == 31) { | ||
1398 | *pTranslatedPinNum = 31; | ||
1399 | *pGroupNum = 17; | ||
1400 | } else | ||
1401 | return -1; | ||
1402 | |||
1403 | *pGroupCfg <<= 24; | ||
1404 | |||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1408 | int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | ||
1409 | struct smscore_gpio_config *pGpioConfig) { | ||
1410 | |||
1411 | u32 totalLen; | ||
1412 | u32 TranslatedPinNum = 0; | ||
1413 | u32 GroupNum = 0; | ||
1414 | u32 ElectricChar; | ||
1415 | u32 groupCfg; | ||
1416 | void *buffer; | ||
1417 | int rc; | ||
1418 | |||
1419 | struct SetGpioMsg { | ||
1420 | struct SmsMsgHdr_ST xMsgHeader; | ||
1421 | u32 msgData[6]; | ||
1422 | } *pMsg; | ||
1423 | |||
1424 | |||
1425 | if (PinNum > MAX_GPIO_PIN_NUMBER) | ||
1426 | return -EINVAL; | ||
1427 | |||
1428 | if (pGpioConfig == NULL) | ||
1429 | return -EINVAL; | ||
1430 | |||
1431 | totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6); | ||
1432 | |||
1433 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
1434 | GFP_KERNEL | GFP_DMA); | ||
1435 | if (!buffer) | ||
1436 | return -ENOMEM; | ||
1437 | |||
1438 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
1439 | |||
1440 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1441 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
1442 | pMsg->xMsgHeader.msgFlags = 0; | ||
1443 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
1444 | pMsg->msgData[0] = PinNum; | ||
1445 | |||
1446 | if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { | ||
1447 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; | ||
1448 | if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, | ||
1449 | &groupCfg) != 0) { | ||
1450 | rc = -EINVAL; | ||
1451 | goto free; | ||
1452 | } | ||
1453 | |||
1454 | pMsg->msgData[1] = TranslatedPinNum; | ||
1455 | pMsg->msgData[2] = GroupNum; | ||
1456 | ElectricChar = (pGpioConfig->PullUpDown) | ||
1457 | | (pGpioConfig->InputCharacteristics << 2) | ||
1458 | | (pGpioConfig->OutputSlewRate << 3) | ||
1459 | | (pGpioConfig->OutputDriving << 4); | ||
1460 | pMsg->msgData[3] = ElectricChar; | ||
1461 | pMsg->msgData[4] = pGpioConfig->Direction; | ||
1462 | pMsg->msgData[5] = groupCfg; | ||
1463 | } else { | ||
1464 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; | ||
1465 | pMsg->msgData[1] = pGpioConfig->PullUpDown; | ||
1466 | pMsg->msgData[2] = pGpioConfig->OutputSlewRate; | ||
1467 | pMsg->msgData[3] = pGpioConfig->OutputDriving; | ||
1468 | pMsg->msgData[4] = pGpioConfig->Direction; | ||
1469 | pMsg->msgData[5] = 0; | ||
1470 | } | ||
1471 | |||
1472 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
1473 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
1474 | &coredev->gpio_configuration_done); | ||
1475 | |||
1476 | if (rc != 0) { | ||
1477 | if (rc == -ETIME) | ||
1478 | sms_err("smscore_gpio_configure timeout"); | ||
1479 | else | ||
1480 | sms_err("smscore_gpio_configure error"); | ||
1481 | } | ||
1482 | free: | ||
1483 | kfree(buffer); | ||
1484 | |||
1485 | return rc; | ||
1486 | } | ||
1487 | |||
1488 | int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, | ||
1489 | u8 NewLevel) { | ||
1490 | |||
1491 | u32 totalLen; | ||
1492 | int rc; | ||
1493 | void *buffer; | ||
1494 | |||
1495 | struct SetGpioMsg { | ||
1496 | struct SmsMsgHdr_ST xMsgHeader; | ||
1497 | u32 msgData[3]; /* keep it 3 ! */ | ||
1498 | } *pMsg; | ||
1499 | |||
1500 | if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER)) | ||
1501 | return -EINVAL; | ||
1502 | |||
1503 | totalLen = sizeof(struct SmsMsgHdr_ST) + | ||
1504 | (3 * sizeof(u32)); /* keep it 3 ! */ | ||
1505 | |||
1506 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
1507 | GFP_KERNEL | GFP_DMA); | ||
1508 | if (!buffer) | ||
1509 | return -ENOMEM; | ||
1510 | |||
1511 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
1512 | |||
1513 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1514 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
1515 | pMsg->xMsgHeader.msgFlags = 0; | ||
1516 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; | ||
1517 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
1518 | pMsg->msgData[0] = PinNum; | ||
1519 | pMsg->msgData[1] = NewLevel; | ||
1520 | |||
1521 | /* Send message to SMS */ | ||
1522 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
1523 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
1524 | &coredev->gpio_set_level_done); | ||
1525 | |||
1526 | if (rc != 0) { | ||
1527 | if (rc == -ETIME) | ||
1528 | sms_err("smscore_gpio_set_level timeout"); | ||
1529 | else | ||
1530 | sms_err("smscore_gpio_set_level error"); | ||
1531 | } | ||
1532 | kfree(buffer); | ||
1533 | |||
1534 | return rc; | ||
1535 | } | ||
1536 | |||
1537 | int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, | ||
1538 | u8 *level) { | ||
1539 | |||
1540 | u32 totalLen; | ||
1541 | int rc; | ||
1542 | void *buffer; | ||
1543 | |||
1544 | struct SetGpioMsg { | ||
1545 | struct SmsMsgHdr_ST xMsgHeader; | ||
1546 | u32 msgData[2]; | ||
1547 | } *pMsg; | ||
1548 | |||
1549 | |||
1550 | if (PinNum > MAX_GPIO_PIN_NUMBER) | ||
1551 | return -EINVAL; | ||
1552 | |||
1553 | totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32)); | ||
1554 | |||
1555 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
1556 | GFP_KERNEL | GFP_DMA); | ||
1557 | if (!buffer) | ||
1558 | return -ENOMEM; | ||
1559 | |||
1560 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
1561 | |||
1562 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1563 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
1564 | pMsg->xMsgHeader.msgFlags = 0; | ||
1565 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ; | ||
1566 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
1567 | pMsg->msgData[0] = PinNum; | ||
1568 | pMsg->msgData[1] = 0; | ||
1569 | |||
1570 | /* Send message to SMS */ | ||
1571 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
1572 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
1573 | &coredev->gpio_get_level_done); | ||
1574 | |||
1575 | if (rc != 0) { | ||
1576 | if (rc == -ETIME) | ||
1577 | sms_err("smscore_gpio_get_level timeout"); | ||
1578 | else | ||
1579 | sms_err("smscore_gpio_get_level error"); | ||
1580 | } | ||
1581 | kfree(buffer); | ||
1582 | |||
1583 | /* Its a race between other gpio_get_level() and the copy of the single | ||
1584 | * global 'coredev->gpio_get_res' to the function's variable 'level' | ||
1585 | */ | ||
1586 | *level = coredev->gpio_get_res; | ||
1587 | |||
1588 | return rc; | ||
1589 | } | ||
1590 | |||
1591 | static int __init smscore_module_init(void) | ||
1592 | { | ||
1593 | int rc = 0; | ||
1594 | |||
1595 | INIT_LIST_HEAD(&g_smscore_notifyees); | ||
1596 | INIT_LIST_HEAD(&g_smscore_devices); | ||
1597 | kmutex_init(&g_smscore_deviceslock); | ||
1598 | |||
1599 | INIT_LIST_HEAD(&g_smscore_registry); | ||
1600 | kmutex_init(&g_smscore_registrylock); | ||
1601 | |||
1602 | return rc; | ||
1603 | } | ||
1604 | |||
1605 | static void __exit smscore_module_exit(void) | ||
1606 | { | ||
1607 | kmutex_lock(&g_smscore_deviceslock); | ||
1608 | while (!list_empty(&g_smscore_notifyees)) { | ||
1609 | struct smscore_device_notifyee_t *notifyee = | ||
1610 | (struct smscore_device_notifyee_t *) | ||
1611 | g_smscore_notifyees.next; | ||
1612 | |||
1613 | list_del(¬ifyee->entry); | ||
1614 | kfree(notifyee); | ||
1615 | } | ||
1616 | kmutex_unlock(&g_smscore_deviceslock); | ||
1617 | |||
1618 | kmutex_lock(&g_smscore_registrylock); | ||
1619 | while (!list_empty(&g_smscore_registry)) { | ||
1620 | struct smscore_registry_entry_t *entry = | ||
1621 | (struct smscore_registry_entry_t *) | ||
1622 | g_smscore_registry.next; | ||
1623 | |||
1624 | list_del(&entry->entry); | ||
1625 | kfree(entry); | ||
1626 | } | ||
1627 | kmutex_unlock(&g_smscore_registrylock); | ||
1628 | |||
1629 | sms_debug(""); | ||
1630 | } | ||
1631 | |||
1632 | module_init(smscore_module_init); | ||
1633 | module_exit(smscore_module_exit); | ||
1634 | |||
1635 | MODULE_DESCRIPTION("Siano MDTV Core module"); | ||
1636 | MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); | ||
1637 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h deleted file mode 100644 index c592ae09039..00000000000 --- a/drivers/media/common/siano/smscoreapi.h +++ /dev/null | |||
@@ -1,775 +0,0 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #ifndef __SMS_CORE_API_H__ | ||
23 | #define __SMS_CORE_API_H__ | ||
24 | |||
25 | #include <linux/device.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/scatterlist.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/wait.h> | ||
32 | #include <linux/timer.h> | ||
33 | |||
34 | #include <asm/page.h> | ||
35 | |||
36 | #include "smsir.h" | ||
37 | |||
38 | #define kmutex_init(_p_) mutex_init(_p_) | ||
39 | #define kmutex_lock(_p_) mutex_lock(_p_) | ||
40 | #define kmutex_trylock(_p_) mutex_trylock(_p_) | ||
41 | #define kmutex_unlock(_p_) mutex_unlock(_p_) | ||
42 | |||
43 | #ifndef min | ||
44 | #define min(a, b) (((a) < (b)) ? (a) : (b)) | ||
45 | #endif | ||
46 | |||
47 | #define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000) | ||
48 | #define SMS_ALLOC_ALIGNMENT 128 | ||
49 | #define SMS_DMA_ALIGNMENT 16 | ||
50 | #define SMS_ALIGN_ADDRESS(addr) \ | ||
51 | ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1)) | ||
52 | |||
53 | #define SMS_DEVICE_FAMILY2 1 | ||
54 | #define SMS_ROM_NO_RESPONSE 2 | ||
55 | #define SMS_DEVICE_NOT_READY 0x8000000 | ||
56 | |||
57 | enum sms_device_type_st { | ||
58 | SMS_STELLAR = 0, | ||
59 | SMS_NOVA_A0, | ||
60 | SMS_NOVA_B0, | ||
61 | SMS_VEGA, | ||
62 | SMS_NUM_OF_DEVICE_TYPES | ||
63 | }; | ||
64 | |||
65 | struct smscore_device_t; | ||
66 | struct smscore_client_t; | ||
67 | struct smscore_buffer_t; | ||
68 | |||
69 | typedef int (*hotplug_t)(struct smscore_device_t *coredev, | ||
70 | struct device *device, int arrival); | ||
71 | |||
72 | typedef int (*setmode_t)(void *context, int mode); | ||
73 | typedef void (*detectmode_t)(void *context, int *mode); | ||
74 | typedef int (*sendrequest_t)(void *context, void *buffer, size_t size); | ||
75 | typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size); | ||
76 | typedef int (*preload_t)(void *context); | ||
77 | typedef int (*postload_t)(void *context); | ||
78 | |||
79 | typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb); | ||
80 | typedef void (*onremove_t)(void *context); | ||
81 | |||
82 | struct smscore_buffer_t { | ||
83 | /* public members, once passed to clients can be changed freely */ | ||
84 | struct list_head entry; | ||
85 | int size; | ||
86 | int offset; | ||
87 | |||
88 | /* private members, read-only for clients */ | ||
89 | void *p; | ||
90 | dma_addr_t phys; | ||
91 | unsigned long offset_in_common; | ||
92 | }; | ||
93 | |||
94 | struct smsdevice_params_t { | ||
95 | struct device *device; | ||
96 | |||
97 | int buffer_size; | ||
98 | int num_buffers; | ||
99 | |||
100 | char devpath[32]; | ||
101 | unsigned long flags; | ||
102 | |||
103 | setmode_t setmode_handler; | ||
104 | detectmode_t detectmode_handler; | ||
105 | sendrequest_t sendrequest_handler; | ||
106 | preload_t preload_handler; | ||
107 | postload_t postload_handler; | ||
108 | |||
109 | void *context; | ||
110 | enum sms_device_type_st device_type; | ||
111 | }; | ||
112 | |||
113 | struct smsclient_params_t { | ||
114 | int initial_id; | ||
115 | int data_type; | ||
116 | onresponse_t onresponse_handler; | ||
117 | onremove_t onremove_handler; | ||
118 | void *context; | ||
119 | }; | ||
120 | |||
121 | struct smscore_device_t { | ||
122 | struct list_head entry; | ||
123 | |||
124 | struct list_head clients; | ||
125 | struct list_head subclients; | ||
126 | spinlock_t clientslock; | ||
127 | |||
128 | struct list_head buffers; | ||
129 | spinlock_t bufferslock; | ||
130 | int num_buffers; | ||
131 | |||
132 | void *common_buffer; | ||
133 | int common_buffer_size; | ||
134 | dma_addr_t common_buffer_phys; | ||
135 | |||
136 | void *context; | ||
137 | struct device *device; | ||
138 | |||
139 | char devpath[32]; | ||
140 | unsigned long device_flags; | ||
141 | |||
142 | setmode_t setmode_handler; | ||
143 | detectmode_t detectmode_handler; | ||
144 | sendrequest_t sendrequest_handler; | ||
145 | preload_t preload_handler; | ||
146 | postload_t postload_handler; | ||
147 | |||
148 | int mode, modes_supported; | ||
149 | |||
150 | /* host <--> device messages */ | ||
151 | struct completion version_ex_done, data_download_done, trigger_done; | ||
152 | struct completion init_device_done, reload_start_done, resume_done; | ||
153 | struct completion gpio_configuration_done, gpio_set_level_done; | ||
154 | struct completion gpio_get_level_done, ir_init_done; | ||
155 | |||
156 | /* Buffer management */ | ||
157 | wait_queue_head_t buffer_mng_waitq; | ||
158 | |||
159 | /* GPIO */ | ||
160 | int gpio_get_res; | ||
161 | |||
162 | /* Target hardware board */ | ||
163 | int board_id; | ||
164 | |||
165 | /* Firmware */ | ||
166 | u8 *fw_buf; | ||
167 | u32 fw_buf_size; | ||
168 | |||
169 | /* Infrared (IR) */ | ||
170 | struct ir_t ir; | ||
171 | |||
172 | int led_state; | ||
173 | }; | ||
174 | |||
175 | /* GPIO definitions for antenna frequency domain control (SMS8021) */ | ||
176 | #define SMS_ANTENNA_GPIO_0 1 | ||
177 | #define SMS_ANTENNA_GPIO_1 0 | ||
178 | |||
179 | #define BW_8_MHZ 0 | ||
180 | #define BW_7_MHZ 1 | ||
181 | #define BW_6_MHZ 2 | ||
182 | #define BW_5_MHZ 3 | ||
183 | #define BW_ISDBT_1SEG 4 | ||
184 | #define BW_ISDBT_3SEG 5 | ||
185 | |||
186 | #define MSG_HDR_FLAG_SPLIT_MSG 4 | ||
187 | |||
188 | #define MAX_GPIO_PIN_NUMBER 31 | ||
189 | |||
190 | #define HIF_TASK 11 | ||
191 | #define SMS_HOST_LIB 150 | ||
192 | #define DVBT_BDA_CONTROL_MSG_ID 201 | ||
193 | |||
194 | #define SMS_MAX_PAYLOAD_SIZE 240 | ||
195 | #define SMS_TUNE_TIMEOUT 500 | ||
196 | |||
197 | #define MSG_SMS_GPIO_CONFIG_REQ 507 | ||
198 | #define MSG_SMS_GPIO_CONFIG_RES 508 | ||
199 | #define MSG_SMS_GPIO_SET_LEVEL_REQ 509 | ||
200 | #define MSG_SMS_GPIO_SET_LEVEL_RES 510 | ||
201 | #define MSG_SMS_GPIO_GET_LEVEL_REQ 511 | ||
202 | #define MSG_SMS_GPIO_GET_LEVEL_RES 512 | ||
203 | #define MSG_SMS_RF_TUNE_REQ 561 | ||
204 | #define MSG_SMS_RF_TUNE_RES 562 | ||
205 | #define MSG_SMS_INIT_DEVICE_REQ 578 | ||
206 | #define MSG_SMS_INIT_DEVICE_RES 579 | ||
207 | #define MSG_SMS_ADD_PID_FILTER_REQ 601 | ||
208 | #define MSG_SMS_ADD_PID_FILTER_RES 602 | ||
209 | #define MSG_SMS_REMOVE_PID_FILTER_REQ 603 | ||
210 | #define MSG_SMS_REMOVE_PID_FILTER_RES 604 | ||
211 | #define MSG_SMS_DAB_CHANNEL 607 | ||
212 | #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 | ||
213 | #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 | ||
214 | #define MSG_SMS_GET_STATISTICS_RES 616 | ||
215 | #define MSG_SMS_GET_STATISTICS_REQ 615 | ||
216 | #define MSG_SMS_HO_PER_SLICES_IND 630 | ||
217 | #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 | ||
218 | #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 | ||
219 | #define MSG_SMS_SLEEP_RESUME_COMP_IND 655 | ||
220 | #define MSG_SMS_DATA_DOWNLOAD_REQ 660 | ||
221 | #define MSG_SMS_DATA_DOWNLOAD_RES 661 | ||
222 | #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 | ||
223 | #define MSG_SMS_SWDOWNLOAD_TRIGGER_RES 665 | ||
224 | #define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ 666 | ||
225 | #define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES 667 | ||
226 | #define MSG_SMS_GET_VERSION_EX_REQ 668 | ||
227 | #define MSG_SMS_GET_VERSION_EX_RES 669 | ||
228 | #define MSG_SMS_SET_CLOCK_OUTPUT_REQ 670 | ||
229 | #define MSG_SMS_I2C_SET_FREQ_REQ 685 | ||
230 | #define MSG_SMS_GENERIC_I2C_REQ 687 | ||
231 | #define MSG_SMS_GENERIC_I2C_RES 688 | ||
232 | #define MSG_SMS_DVBT_BDA_DATA 693 | ||
233 | #define MSG_SW_RELOAD_REQ 697 | ||
234 | #define MSG_SMS_DATA_MSG 699 | ||
235 | #define MSG_SW_RELOAD_START_REQ 702 | ||
236 | #define MSG_SW_RELOAD_START_RES 703 | ||
237 | #define MSG_SW_RELOAD_EXEC_REQ 704 | ||
238 | #define MSG_SW_RELOAD_EXEC_RES 705 | ||
239 | #define MSG_SMS_SPI_INT_LINE_SET_REQ 710 | ||
240 | #define MSG_SMS_GPIO_CONFIG_EX_REQ 712 | ||
241 | #define MSG_SMS_GPIO_CONFIG_EX_RES 713 | ||
242 | #define MSG_SMS_ISDBT_TUNE_REQ 776 | ||
243 | #define MSG_SMS_ISDBT_TUNE_RES 777 | ||
244 | #define MSG_SMS_TRANSMISSION_IND 782 | ||
245 | #define MSG_SMS_START_IR_REQ 800 | ||
246 | #define MSG_SMS_START_IR_RES 801 | ||
247 | #define MSG_SMS_IR_SAMPLES_IND 802 | ||
248 | #define MSG_SMS_SIGNAL_DETECTED_IND 827 | ||
249 | #define MSG_SMS_NO_SIGNAL_IND 828 | ||
250 | |||
251 | #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \ | ||
252 | (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \ | ||
253 | (ptr)->msgLength = len; (ptr)->msgFlags = 0; \ | ||
254 | } while (0) | ||
255 | |||
256 | #define SMS_INIT_MSG(ptr, type, len) \ | ||
257 | SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len) | ||
258 | |||
259 | enum SMS_DVB3_EVENTS { | ||
260 | DVB3_EVENT_INIT = 0, | ||
261 | DVB3_EVENT_SLEEP, | ||
262 | DVB3_EVENT_HOTPLUG, | ||
263 | DVB3_EVENT_FE_LOCK, | ||
264 | DVB3_EVENT_FE_UNLOCK, | ||
265 | DVB3_EVENT_UNC_OK, | ||
266 | DVB3_EVENT_UNC_ERR | ||
267 | }; | ||
268 | |||
269 | enum SMS_DEVICE_MODE { | ||
270 | DEVICE_MODE_NONE = -1, | ||
271 | DEVICE_MODE_DVBT = 0, | ||
272 | DEVICE_MODE_DVBH, | ||
273 | DEVICE_MODE_DAB_TDMB, | ||
274 | DEVICE_MODE_DAB_TDMB_DABIP, | ||
275 | DEVICE_MODE_DVBT_BDA, | ||
276 | DEVICE_MODE_ISDBT, | ||
277 | DEVICE_MODE_ISDBT_BDA, | ||
278 | DEVICE_MODE_CMMB, | ||
279 | DEVICE_MODE_RAW_TUNER, | ||
280 | DEVICE_MODE_MAX, | ||
281 | }; | ||
282 | |||
283 | struct SmsMsgHdr_ST { | ||
284 | u16 msgType; | ||
285 | u8 msgSrcId; | ||
286 | u8 msgDstId; | ||
287 | u16 msgLength; /* Length of entire message, including header */ | ||
288 | u16 msgFlags; | ||
289 | }; | ||
290 | |||
291 | struct SmsMsgData_ST { | ||
292 | struct SmsMsgHdr_ST xMsgHeader; | ||
293 | u32 msgData[1]; | ||
294 | }; | ||
295 | |||
296 | struct SmsMsgData_ST2 { | ||
297 | struct SmsMsgHdr_ST xMsgHeader; | ||
298 | u32 msgData[2]; | ||
299 | }; | ||
300 | |||
301 | struct SmsDataDownload_ST { | ||
302 | struct SmsMsgHdr_ST xMsgHeader; | ||
303 | u32 MemAddr; | ||
304 | u8 Payload[SMS_MAX_PAYLOAD_SIZE]; | ||
305 | }; | ||
306 | |||
307 | struct SmsVersionRes_ST { | ||
308 | struct SmsMsgHdr_ST xMsgHeader; | ||
309 | |||
310 | u16 ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */ | ||
311 | u8 Step; /* 0 - Step A */ | ||
312 | u8 MetalFix; /* 0 - Metal 0 */ | ||
313 | |||
314 | /* FirmwareId 0xFF if ROM, otherwise the | ||
315 | * value indicated by SMSHOSTLIB_DEVICE_MODES_E */ | ||
316 | u8 FirmwareId; | ||
317 | /* SupportedProtocols Bitwise OR combination of | ||
318 | * supported protocols */ | ||
319 | u8 SupportedProtocols; | ||
320 | |||
321 | u8 VersionMajor; | ||
322 | u8 VersionMinor; | ||
323 | u8 VersionPatch; | ||
324 | u8 VersionFieldPatch; | ||
325 | |||
326 | u8 RomVersionMajor; | ||
327 | u8 RomVersionMinor; | ||
328 | u8 RomVersionPatch; | ||
329 | u8 RomVersionFieldPatch; | ||
330 | |||
331 | u8 TextLabel[34]; | ||
332 | }; | ||
333 | |||
334 | struct SmsFirmware_ST { | ||
335 | u32 CheckSum; | ||
336 | u32 Length; | ||
337 | u32 StartAddress; | ||
338 | u8 Payload[1]; | ||
339 | }; | ||
340 | |||
341 | /* Statistics information returned as response for | ||
342 | * SmsHostApiGetStatistics_Req */ | ||
343 | struct SMSHOSTLIB_STATISTICS_ST { | ||
344 | u32 Reserved; /* Reserved */ | ||
345 | |||
346 | /* Common parameters */ | ||
347 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
348 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
349 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
350 | |||
351 | /* Reception quality */ | ||
352 | s32 SNR; /* dB */ | ||
353 | u32 BER; /* Post Viterbi BER [1E-5] */ | ||
354 | u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ | ||
355 | u32 TS_PER; /* Transport stream PER, | ||
356 | 0xFFFFFFFF indicate N/A, valid only for DVB-T/H */ | ||
357 | u32 MFER; /* DVB-H frame error rate in percentage, | ||
358 | 0xFFFFFFFF indicate N/A, valid only for DVB-H */ | ||
359 | s32 RSSI; /* dBm */ | ||
360 | s32 InBandPwr; /* In band power in dBM */ | ||
361 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ | ||
362 | |||
363 | /* Transmission parameters */ | ||
364 | u32 Frequency; /* Frequency in Hz */ | ||
365 | u32 Bandwidth; /* Bandwidth in MHz, valid only for DVB-T/H */ | ||
366 | u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, | ||
367 | for DVB-T/H FFT mode carriers in Kilos */ | ||
368 | u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET, | ||
369 | valid only for DVB-T/H */ | ||
370 | u32 GuardInterval; /* Guard Interval from | ||
371 | SMSHOSTLIB_GUARD_INTERVALS_ET, valid only for DVB-T/H */ | ||
372 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, | ||
373 | valid only for DVB-T/H */ | ||
374 | u32 LPCodeRate; /* Low Priority Code Rate from | ||
375 | SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */ | ||
376 | u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET, | ||
377 | valid only for DVB-T/H */ | ||
378 | u32 Constellation; /* Constellation from | ||
379 | SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */ | ||
380 | |||
381 | /* Burst parameters, valid only for DVB-H */ | ||
382 | u32 BurstSize; /* Current burst size in bytes, | ||
383 | valid only for DVB-H */ | ||
384 | u32 BurstDuration; /* Current burst duration in mSec, | ||
385 | valid only for DVB-H */ | ||
386 | u32 BurstCycleTime; /* Current burst cycle time in mSec, | ||
387 | valid only for DVB-H */ | ||
388 | u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec, | ||
389 | as calculated by demodulator, valid only for DVB-H */ | ||
390 | u32 NumOfRows; /* Number of rows in MPE table, | ||
391 | valid only for DVB-H */ | ||
392 | u32 NumOfPaddCols; /* Number of padding columns in MPE table, | ||
393 | valid only for DVB-H */ | ||
394 | u32 NumOfPunctCols; /* Number of puncturing columns in MPE table, | ||
395 | valid only for DVB-H */ | ||
396 | u32 ErrorTSPackets; /* Number of erroneous | ||
397 | transport-stream packets */ | ||
398 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
399 | u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include | ||
400 | errors after MPE RS decoding */ | ||
401 | u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors | ||
402 | after MPE RS decoding */ | ||
403 | u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were | ||
404 | corrected by MPE RS decoding */ | ||
405 | /* Common params */ | ||
406 | u32 BERErrorCount; /* Number of errornous SYNC bits. */ | ||
407 | u32 BERBitCount; /* Total number of SYNC bits. */ | ||
408 | |||
409 | /* Interface information */ | ||
410 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ | ||
411 | |||
412 | /* DAB/T-DMB */ | ||
413 | u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ | ||
414 | |||
415 | /* DVB-H TPS parameters */ | ||
416 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; | ||
417 | if set to 0xFFFFFFFF cell_id not yet recovered */ | ||
418 | u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - | ||
419 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
420 | u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - | ||
421 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
422 | |||
423 | u32 NumMPEReceived; /* DVB-H, Num MPE section received */ | ||
424 | |||
425 | u32 ReservedFields[10]; /* Reserved */ | ||
426 | }; | ||
427 | |||
428 | struct SmsMsgStatisticsInfo_ST { | ||
429 | u32 RequestResult; | ||
430 | |||
431 | struct SMSHOSTLIB_STATISTICS_ST Stat; | ||
432 | |||
433 | /* Split the calc of the SNR in DAB */ | ||
434 | u32 Signal; /* dB */ | ||
435 | u32 Noise; /* dB */ | ||
436 | |||
437 | }; | ||
438 | |||
439 | struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST { | ||
440 | /* Per-layer information */ | ||
441 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, | ||
442 | * 255 means layer does not exist */ | ||
443 | u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET, | ||
444 | * 255 means layer does not exist */ | ||
445 | u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ | ||
446 | u32 BERErrorCount; /* Post Viterbi Error Bits Count */ | ||
447 | u32 BERBitCount; /* Post Viterbi Total Bits Count */ | ||
448 | u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ | ||
449 | u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */ | ||
450 | u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ | ||
451 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
452 | u32 TILdepthI; /* Time interleaver depth I parameter, | ||
453 | * 255 means layer does not exist */ | ||
454 | u32 NumberOfSegments; /* Number of segments in layer A, | ||
455 | * 255 means layer does not exist */ | ||
456 | u32 TMCCErrors; /* TMCC errors */ | ||
457 | }; | ||
458 | |||
459 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST { | ||
460 | u32 StatisticsType; /* Enumerator identifying the type of the | ||
461 | * structure. Values are the same as | ||
462 | * SMSHOSTLIB_DEVICE_MODES_E | ||
463 | * | ||
464 | * This field MUST always be first in any | ||
465 | * statistics structure */ | ||
466 | |||
467 | u32 FullSize; /* Total size of the structure returned by the modem. | ||
468 | * If the size requested by the host is smaller than | ||
469 | * FullSize, the struct will be truncated */ | ||
470 | |||
471 | /* Common parameters */ | ||
472 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
473 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
474 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
475 | |||
476 | /* Reception quality */ | ||
477 | s32 SNR; /* dB */ | ||
478 | s32 RSSI; /* dBm */ | ||
479 | s32 InBandPwr; /* In band power in dBM */ | ||
480 | s32 CarrierOffset; /* Carrier Offset in Hz */ | ||
481 | |||
482 | /* Transmission parameters */ | ||
483 | u32 Frequency; /* Frequency in Hz */ | ||
484 | u32 Bandwidth; /* Bandwidth in MHz */ | ||
485 | u32 TransmissionMode; /* ISDB-T transmission mode */ | ||
486 | u32 ModemState; /* 0 - Acquisition, 1 - Locked */ | ||
487 | u32 GuardInterval; /* Guard Interval, 1 divided by value */ | ||
488 | u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */ | ||
489 | u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */ | ||
490 | u32 NumOfLayers; /* Number of ISDB-T layers in the network */ | ||
491 | |||
492 | /* Per-layer information */ | ||
493 | /* Layers A, B and C */ | ||
494 | struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3]; | ||
495 | /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */ | ||
496 | |||
497 | /* Interface information */ | ||
498 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ | ||
499 | }; | ||
500 | |||
501 | struct PID_STATISTICS_DATA_S { | ||
502 | struct PID_BURST_S { | ||
503 | u32 size; | ||
504 | u32 padding_cols; | ||
505 | u32 punct_cols; | ||
506 | u32 duration; | ||
507 | u32 cycle; | ||
508 | u32 calc_cycle; | ||
509 | } burst; | ||
510 | |||
511 | u32 tot_tbl_cnt; | ||
512 | u32 invalid_tbl_cnt; | ||
513 | u32 tot_cor_tbl; | ||
514 | }; | ||
515 | |||
516 | struct PID_DATA_S { | ||
517 | u32 pid; | ||
518 | u32 num_rows; | ||
519 | struct PID_STATISTICS_DATA_S pid_statistics; | ||
520 | }; | ||
521 | |||
522 | #define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1) | ||
523 | #define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth) | ||
524 | #define CORRECT_STAT_TRANSMISSON_MODE(_stat) \ | ||
525 | if (_stat.TransmissionMode == 0) \ | ||
526 | _stat.TransmissionMode = 2; \ | ||
527 | else if (_stat.TransmissionMode == 1) \ | ||
528 | _stat.TransmissionMode = 8; \ | ||
529 | else \ | ||
530 | _stat.TransmissionMode = 4; | ||
531 | |||
532 | struct TRANSMISSION_STATISTICS_S { | ||
533 | u32 Frequency; /* Frequency in Hz */ | ||
534 | u32 Bandwidth; /* Bandwidth in MHz */ | ||
535 | u32 TransmissionMode; /* FFT mode carriers in Kilos */ | ||
536 | u32 GuardInterval; /* Guard Interval from | ||
537 | SMSHOSTLIB_GUARD_INTERVALS_ET */ | ||
538 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ | ||
539 | u32 LPCodeRate; /* Low Priority Code Rate from | ||
540 | SMSHOSTLIB_CODE_RATE_ET */ | ||
541 | u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ | ||
542 | u32 Constellation; /* Constellation from | ||
543 | SMSHOSTLIB_CONSTELLATION_ET */ | ||
544 | |||
545 | /* DVB-H TPS parameters */ | ||
546 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; | ||
547 | if set to 0xFFFFFFFF cell_id not yet recovered */ | ||
548 | u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - | ||
549 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
550 | u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - | ||
551 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
552 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
553 | }; | ||
554 | |||
555 | struct RECEPTION_STATISTICS_S { | ||
556 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
557 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
558 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
559 | |||
560 | u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ | ||
561 | s32 SNR; /* dB */ | ||
562 | u32 BER; /* Post Viterbi BER [1E-5] */ | ||
563 | u32 BERErrorCount; /* Number of erronous SYNC bits. */ | ||
564 | u32 BERBitCount; /* Total number of SYNC bits. */ | ||
565 | u32 TS_PER; /* Transport stream PER, | ||
566 | 0xFFFFFFFF indicate N/A */ | ||
567 | u32 MFER; /* DVB-H frame error rate in percentage, | ||
568 | 0xFFFFFFFF indicate N/A, valid only for DVB-H */ | ||
569 | s32 RSSI; /* dBm */ | ||
570 | s32 InBandPwr; /* In band power in dBM */ | ||
571 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ | ||
572 | u32 ErrorTSPackets; /* Number of erroneous | ||
573 | transport-stream packets */ | ||
574 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
575 | |||
576 | s32 MRC_SNR; /* dB */ | ||
577 | s32 MRC_RSSI; /* dBm */ | ||
578 | s32 MRC_InBandPwr; /* In band power in dBM */ | ||
579 | }; | ||
580 | |||
581 | |||
582 | /* Statistics information returned as response for | ||
583 | * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */ | ||
584 | struct SMSHOSTLIB_STATISTICS_DVB_S { | ||
585 | /* Reception */ | ||
586 | struct RECEPTION_STATISTICS_S ReceptionData; | ||
587 | |||
588 | /* Transmission parameters */ | ||
589 | struct TRANSMISSION_STATISTICS_S TransmissionData; | ||
590 | |||
591 | /* Burst parameters, valid only for DVB-H */ | ||
592 | #define SRVM_MAX_PID_FILTERS 8 | ||
593 | struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS]; | ||
594 | }; | ||
595 | |||
596 | struct SRVM_SIGNAL_STATUS_S { | ||
597 | u32 result; | ||
598 | u32 snr; | ||
599 | u32 tsPackets; | ||
600 | u32 etsPackets; | ||
601 | u32 constellation; | ||
602 | u32 hpCode; | ||
603 | u32 tpsSrvIndLP; | ||
604 | u32 tpsSrvIndHP; | ||
605 | u32 cellId; | ||
606 | u32 reason; | ||
607 | |||
608 | s32 inBandPower; | ||
609 | u32 requestId; | ||
610 | }; | ||
611 | |||
612 | struct SMSHOSTLIB_I2C_REQ_ST { | ||
613 | u32 DeviceAddress; /* I2c device address */ | ||
614 | u32 WriteCount; /* number of bytes to write */ | ||
615 | u32 ReadCount; /* number of bytes to read */ | ||
616 | u8 Data[1]; | ||
617 | }; | ||
618 | |||
619 | struct SMSHOSTLIB_I2C_RES_ST { | ||
620 | u32 Status; /* non-zero value in case of failure */ | ||
621 | u32 ReadCount; /* number of bytes read */ | ||
622 | u8 Data[1]; | ||
623 | }; | ||
624 | |||
625 | |||
626 | struct smscore_config_gpio { | ||
627 | #define SMS_GPIO_DIRECTION_INPUT 0 | ||
628 | #define SMS_GPIO_DIRECTION_OUTPUT 1 | ||
629 | u8 direction; | ||
630 | |||
631 | #define SMS_GPIO_PULLUPDOWN_NONE 0 | ||
632 | #define SMS_GPIO_PULLUPDOWN_PULLDOWN 1 | ||
633 | #define SMS_GPIO_PULLUPDOWN_PULLUP 2 | ||
634 | #define SMS_GPIO_PULLUPDOWN_KEEPER 3 | ||
635 | u8 pullupdown; | ||
636 | |||
637 | #define SMS_GPIO_INPUTCHARACTERISTICS_NORMAL 0 | ||
638 | #define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1 | ||
639 | u8 inputcharacteristics; | ||
640 | |||
641 | #define SMS_GPIO_OUTPUTSLEWRATE_FAST 0 | ||
642 | #define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1 | ||
643 | u8 outputslewrate; | ||
644 | |||
645 | #define SMS_GPIO_OUTPUTDRIVING_4mA 0 | ||
646 | #define SMS_GPIO_OUTPUTDRIVING_8mA 1 | ||
647 | #define SMS_GPIO_OUTPUTDRIVING_12mA 2 | ||
648 | #define SMS_GPIO_OUTPUTDRIVING_16mA 3 | ||
649 | u8 outputdriving; | ||
650 | }; | ||
651 | |||
652 | struct smscore_gpio_config { | ||
653 | #define SMS_GPIO_DIRECTION_INPUT 0 | ||
654 | #define SMS_GPIO_DIRECTION_OUTPUT 1 | ||
655 | u8 Direction; | ||
656 | |||
657 | #define SMS_GPIO_PULL_UP_DOWN_NONE 0 | ||
658 | #define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1 | ||
659 | #define SMS_GPIO_PULL_UP_DOWN_PULLUP 2 | ||
660 | #define SMS_GPIO_PULL_UP_DOWN_KEEPER 3 | ||
661 | u8 PullUpDown; | ||
662 | |||
663 | #define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0 | ||
664 | #define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1 | ||
665 | u8 InputCharacteristics; | ||
666 | |||
667 | #define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW 1 /* 10xx */ | ||
668 | #define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0 /* 10xx */ | ||
669 | |||
670 | |||
671 | #define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS 0 /* 11xx */ | ||
672 | #define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS 1 /* 11xx */ | ||
673 | #define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS 2 /* 11xx */ | ||
674 | #define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS 3 /* 11xx */ | ||
675 | u8 OutputSlewRate; | ||
676 | |||
677 | #define SMS_GPIO_OUTPUT_DRIVING_S_4mA 0 /* 10xx */ | ||
678 | #define SMS_GPIO_OUTPUT_DRIVING_S_8mA 1 /* 10xx */ | ||
679 | #define SMS_GPIO_OUTPUT_DRIVING_S_12mA 2 /* 10xx */ | ||
680 | #define SMS_GPIO_OUTPUT_DRIVING_S_16mA 3 /* 10xx */ | ||
681 | |||
682 | #define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */ | ||
683 | #define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */ | ||
684 | #define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */ | ||
685 | #define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */ | ||
686 | #define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */ | ||
687 | #define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */ | ||
688 | #define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */ | ||
689 | #define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */ | ||
690 | u8 OutputDriving; | ||
691 | }; | ||
692 | |||
693 | extern void smscore_registry_setmode(char *devpath, int mode); | ||
694 | extern int smscore_registry_getmode(char *devpath); | ||
695 | |||
696 | extern int smscore_register_hotplug(hotplug_t hotplug); | ||
697 | extern void smscore_unregister_hotplug(hotplug_t hotplug); | ||
698 | |||
699 | extern int smscore_register_device(struct smsdevice_params_t *params, | ||
700 | struct smscore_device_t **coredev); | ||
701 | extern void smscore_unregister_device(struct smscore_device_t *coredev); | ||
702 | |||
703 | extern int smscore_start_device(struct smscore_device_t *coredev); | ||
704 | extern int smscore_load_firmware(struct smscore_device_t *coredev, | ||
705 | char *filename, | ||
706 | loadfirmware_t loadfirmware_handler); | ||
707 | |||
708 | extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode); | ||
709 | extern int smscore_get_device_mode(struct smscore_device_t *coredev); | ||
710 | |||
711 | extern int smscore_register_client(struct smscore_device_t *coredev, | ||
712 | struct smsclient_params_t *params, | ||
713 | struct smscore_client_t **client); | ||
714 | extern void smscore_unregister_client(struct smscore_client_t *client); | ||
715 | |||
716 | extern int smsclient_sendrequest(struct smscore_client_t *client, | ||
717 | void *buffer, size_t size); | ||
718 | extern void smscore_onresponse(struct smscore_device_t *coredev, | ||
719 | struct smscore_buffer_t *cb); | ||
720 | |||
721 | extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); | ||
722 | extern int smscore_map_common_buffer(struct smscore_device_t *coredev, | ||
723 | struct vm_area_struct *vma); | ||
724 | extern int smscore_get_fw_filename(struct smscore_device_t *coredev, | ||
725 | int mode, char *filename); | ||
726 | extern int smscore_send_fw_file(struct smscore_device_t *coredev, | ||
727 | u8 *ufwbuf, int size); | ||
728 | |||
729 | extern | ||
730 | struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev); | ||
731 | extern void smscore_putbuffer(struct smscore_device_t *coredev, | ||
732 | struct smscore_buffer_t *cb); | ||
733 | |||
734 | /* old GPIO management */ | ||
735 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, | ||
736 | struct smscore_config_gpio *pinconfig); | ||
737 | int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level); | ||
738 | |||
739 | /* new GPIO management */ | ||
740 | extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | ||
741 | struct smscore_gpio_config *pGpioConfig); | ||
742 | extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, | ||
743 | u8 NewLevel); | ||
744 | extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, | ||
745 | u8 *level); | ||
746 | |||
747 | void smscore_set_board_id(struct smscore_device_t *core, int id); | ||
748 | int smscore_get_board_id(struct smscore_device_t *core); | ||
749 | |||
750 | int smscore_led_state(struct smscore_device_t *core, int led); | ||
751 | |||
752 | |||
753 | /* ------------------------------------------------------------------------ */ | ||
754 | |||
755 | #define DBG_INFO 1 | ||
756 | #define DBG_ADV 2 | ||
757 | |||
758 | #define sms_printk(kern, fmt, arg...) \ | ||
759 | printk(kern "%s: " fmt "\n", __func__, ##arg) | ||
760 | |||
761 | #define dprintk(kern, lvl, fmt, arg...) do {\ | ||
762 | if (sms_dbg & lvl) \ | ||
763 | sms_printk(kern, fmt, ##arg); } while (0) | ||
764 | |||
765 | #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg) | ||
766 | #define sms_err(fmt, arg...) \ | ||
767 | sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg) | ||
768 | #define sms_warn(fmt, arg...) sms_printk(KERN_WARNING, fmt, ##arg) | ||
769 | #define sms_info(fmt, arg...) \ | ||
770 | dprintk(KERN_INFO, DBG_INFO, fmt, ##arg) | ||
771 | #define sms_debug(fmt, arg...) \ | ||
772 | dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg) | ||
773 | |||
774 | |||
775 | #endif /* __SMS_CORE_API_H__ */ | ||
diff --git a/drivers/media/common/siano/smsdvb.c b/drivers/media/common/siano/smsdvb.c deleted file mode 100644 index aa77e54a8fa..00000000000 --- a/drivers/media/common/siano/smsdvb.c +++ /dev/null | |||
@@ -1,1078 +0,0 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2008, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | |||
26 | #include "dmxdev.h" | ||
27 | #include "dvbdev.h" | ||
28 | #include "dvb_demux.h" | ||
29 | #include "dvb_frontend.h" | ||
30 | |||
31 | #include "smscoreapi.h" | ||
32 | #include "smsendian.h" | ||
33 | #include "sms-cards.h" | ||
34 | |||
35 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
36 | |||
37 | struct smsdvb_client_t { | ||
38 | struct list_head entry; | ||
39 | |||
40 | struct smscore_device_t *coredev; | ||
41 | struct smscore_client_t *smsclient; | ||
42 | |||
43 | struct dvb_adapter adapter; | ||
44 | struct dvb_demux demux; | ||
45 | struct dmxdev dmxdev; | ||
46 | struct dvb_frontend frontend; | ||
47 | |||
48 | fe_status_t fe_status; | ||
49 | |||
50 | struct completion tune_done; | ||
51 | |||
52 | struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb; | ||
53 | int event_fe_state; | ||
54 | int event_unc_state; | ||
55 | }; | ||
56 | |||
57 | static struct list_head g_smsdvb_clients; | ||
58 | static struct mutex g_smsdvb_clientslock; | ||
59 | |||
60 | static int sms_dbg; | ||
61 | module_param_named(debug, sms_dbg, int, 0644); | ||
62 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | ||
63 | |||
64 | /* Events that may come from DVB v3 adapter */ | ||
65 | static void sms_board_dvb3_event(struct smsdvb_client_t *client, | ||
66 | enum SMS_DVB3_EVENTS event) { | ||
67 | |||
68 | struct smscore_device_t *coredev = client->coredev; | ||
69 | switch (event) { | ||
70 | case DVB3_EVENT_INIT: | ||
71 | sms_debug("DVB3_EVENT_INIT"); | ||
72 | sms_board_event(coredev, BOARD_EVENT_BIND); | ||
73 | break; | ||
74 | case DVB3_EVENT_SLEEP: | ||
75 | sms_debug("DVB3_EVENT_SLEEP"); | ||
76 | sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND); | ||
77 | break; | ||
78 | case DVB3_EVENT_HOTPLUG: | ||
79 | sms_debug("DVB3_EVENT_HOTPLUG"); | ||
80 | sms_board_event(coredev, BOARD_EVENT_POWER_INIT); | ||
81 | break; | ||
82 | case DVB3_EVENT_FE_LOCK: | ||
83 | if (client->event_fe_state != DVB3_EVENT_FE_LOCK) { | ||
84 | client->event_fe_state = DVB3_EVENT_FE_LOCK; | ||
85 | sms_debug("DVB3_EVENT_FE_LOCK"); | ||
86 | sms_board_event(coredev, BOARD_EVENT_FE_LOCK); | ||
87 | } | ||
88 | break; | ||
89 | case DVB3_EVENT_FE_UNLOCK: | ||
90 | if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) { | ||
91 | client->event_fe_state = DVB3_EVENT_FE_UNLOCK; | ||
92 | sms_debug("DVB3_EVENT_FE_UNLOCK"); | ||
93 | sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK); | ||
94 | } | ||
95 | break; | ||
96 | case DVB3_EVENT_UNC_OK: | ||
97 | if (client->event_unc_state != DVB3_EVENT_UNC_OK) { | ||
98 | client->event_unc_state = DVB3_EVENT_UNC_OK; | ||
99 | sms_debug("DVB3_EVENT_UNC_OK"); | ||
100 | sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK); | ||
101 | } | ||
102 | break; | ||
103 | case DVB3_EVENT_UNC_ERR: | ||
104 | if (client->event_unc_state != DVB3_EVENT_UNC_ERR) { | ||
105 | client->event_unc_state = DVB3_EVENT_UNC_ERR; | ||
106 | sms_debug("DVB3_EVENT_UNC_ERR"); | ||
107 | sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS); | ||
108 | } | ||
109 | break; | ||
110 | |||
111 | default: | ||
112 | sms_err("Unknown dvb3 api event"); | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | |||
118 | static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData, | ||
119 | struct SMSHOSTLIB_STATISTICS_ST *p) | ||
120 | { | ||
121 | if (sms_dbg & 2) { | ||
122 | printk(KERN_DEBUG "Reserved = %d", p->Reserved); | ||
123 | printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); | ||
124 | printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); | ||
125 | printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); | ||
126 | printk(KERN_DEBUG "SNR = %d", p->SNR); | ||
127 | printk(KERN_DEBUG "BER = %d", p->BER); | ||
128 | printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC); | ||
129 | printk(KERN_DEBUG "TS_PER = %d", p->TS_PER); | ||
130 | printk(KERN_DEBUG "MFER = %d", p->MFER); | ||
131 | printk(KERN_DEBUG "RSSI = %d", p->RSSI); | ||
132 | printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); | ||
133 | printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); | ||
134 | printk(KERN_DEBUG "Frequency = %d", p->Frequency); | ||
135 | printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); | ||
136 | printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); | ||
137 | printk(KERN_DEBUG "ModemState = %d", p->ModemState); | ||
138 | printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); | ||
139 | printk(KERN_DEBUG "CodeRate = %d", p->CodeRate); | ||
140 | printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate); | ||
141 | printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy); | ||
142 | printk(KERN_DEBUG "Constellation = %d", p->Constellation); | ||
143 | printk(KERN_DEBUG "BurstSize = %d", p->BurstSize); | ||
144 | printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration); | ||
145 | printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime); | ||
146 | printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime); | ||
147 | printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows); | ||
148 | printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols); | ||
149 | printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols); | ||
150 | printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets); | ||
151 | printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets); | ||
152 | printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs); | ||
153 | printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs); | ||
154 | printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs); | ||
155 | printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount); | ||
156 | printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount); | ||
157 | printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); | ||
158 | printk(KERN_DEBUG "PreBER = %d", p->PreBER); | ||
159 | printk(KERN_DEBUG "CellId = %d", p->CellId); | ||
160 | printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP); | ||
161 | printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP); | ||
162 | printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived); | ||
163 | } | ||
164 | |||
165 | pReceptionData->IsDemodLocked = p->IsDemodLocked; | ||
166 | |||
167 | pReceptionData->SNR = p->SNR; | ||
168 | pReceptionData->BER = p->BER; | ||
169 | pReceptionData->BERErrorCount = p->BERErrorCount; | ||
170 | pReceptionData->InBandPwr = p->InBandPwr; | ||
171 | pReceptionData->ErrorTSPackets = p->ErrorTSPackets; | ||
172 | }; | ||
173 | |||
174 | |||
175 | static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData, | ||
176 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p) | ||
177 | { | ||
178 | int i; | ||
179 | |||
180 | if (sms_dbg & 2) { | ||
181 | printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); | ||
182 | printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); | ||
183 | printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); | ||
184 | printk(KERN_DEBUG "SNR = %d", p->SNR); | ||
185 | printk(KERN_DEBUG "RSSI = %d", p->RSSI); | ||
186 | printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); | ||
187 | printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); | ||
188 | printk(KERN_DEBUG "Frequency = %d", p->Frequency); | ||
189 | printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); | ||
190 | printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); | ||
191 | printk(KERN_DEBUG "ModemState = %d", p->ModemState); | ||
192 | printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); | ||
193 | printk(KERN_DEBUG "SystemType = %d", p->SystemType); | ||
194 | printk(KERN_DEBUG "PartialReception = %d", p->PartialReception); | ||
195 | printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers); | ||
196 | printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); | ||
197 | |||
198 | for (i = 0; i < 3; i++) { | ||
199 | printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate); | ||
200 | printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation); | ||
201 | printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER); | ||
202 | printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount); | ||
203 | printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount); | ||
204 | printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER); | ||
205 | printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER); | ||
206 | printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets); | ||
207 | printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets); | ||
208 | printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI); | ||
209 | printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments); | ||
210 | printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | pReceptionData->IsDemodLocked = p->IsDemodLocked; | ||
215 | |||
216 | pReceptionData->SNR = p->SNR; | ||
217 | pReceptionData->InBandPwr = p->InBandPwr; | ||
218 | |||
219 | pReceptionData->ErrorTSPackets = 0; | ||
220 | pReceptionData->BER = 0; | ||
221 | pReceptionData->BERErrorCount = 0; | ||
222 | for (i = 0; i < 3; i++) { | ||
223 | pReceptionData->BER += p->LayerInfo[i].BER; | ||
224 | pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount; | ||
225 | pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | ||
230 | { | ||
231 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; | ||
232 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) | ||
233 | + cb->offset); | ||
234 | u32 *pMsgData = (u32 *) phdr + 1; | ||
235 | /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ | ||
236 | bool is_status_update = false; | ||
237 | |||
238 | smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); | ||
239 | |||
240 | switch (phdr->msgType) { | ||
241 | case MSG_SMS_DVBT_BDA_DATA: | ||
242 | dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1), | ||
243 | cb->size - sizeof(struct SmsMsgHdr_ST)); | ||
244 | break; | ||
245 | |||
246 | case MSG_SMS_RF_TUNE_RES: | ||
247 | case MSG_SMS_ISDBT_TUNE_RES: | ||
248 | complete(&client->tune_done); | ||
249 | break; | ||
250 | |||
251 | case MSG_SMS_SIGNAL_DETECTED_IND: | ||
252 | sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); | ||
253 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; | ||
254 | is_status_update = true; | ||
255 | break; | ||
256 | |||
257 | case MSG_SMS_NO_SIGNAL_IND: | ||
258 | sms_info("MSG_SMS_NO_SIGNAL_IND"); | ||
259 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; | ||
260 | is_status_update = true; | ||
261 | break; | ||
262 | |||
263 | case MSG_SMS_TRANSMISSION_IND: { | ||
264 | sms_info("MSG_SMS_TRANSMISSION_IND"); | ||
265 | |||
266 | pMsgData++; | ||
267 | memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, | ||
268 | sizeof(struct TRANSMISSION_STATISTICS_S)); | ||
269 | |||
270 | /* Mo need to correct guard interval | ||
271 | * (as opposed to old statistics message). | ||
272 | */ | ||
273 | CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); | ||
274 | CORRECT_STAT_TRANSMISSON_MODE( | ||
275 | client->sms_stat_dvb.TransmissionData); | ||
276 | is_status_update = true; | ||
277 | break; | ||
278 | } | ||
279 | case MSG_SMS_HO_PER_SLICES_IND: { | ||
280 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
281 | &client->sms_stat_dvb.ReceptionData; | ||
282 | struct SRVM_SIGNAL_STATUS_S SignalStatusData; | ||
283 | |||
284 | /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ | ||
285 | pMsgData++; | ||
286 | SignalStatusData.result = pMsgData[0]; | ||
287 | SignalStatusData.snr = pMsgData[1]; | ||
288 | SignalStatusData.inBandPower = (s32) pMsgData[2]; | ||
289 | SignalStatusData.tsPackets = pMsgData[3]; | ||
290 | SignalStatusData.etsPackets = pMsgData[4]; | ||
291 | SignalStatusData.constellation = pMsgData[5]; | ||
292 | SignalStatusData.hpCode = pMsgData[6]; | ||
293 | SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; | ||
294 | SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; | ||
295 | SignalStatusData.cellId = pMsgData[9] & 0xFFFF; | ||
296 | SignalStatusData.reason = pMsgData[10]; | ||
297 | SignalStatusData.requestId = pMsgData[11]; | ||
298 | pReceptionData->IsRfLocked = pMsgData[16]; | ||
299 | pReceptionData->IsDemodLocked = pMsgData[17]; | ||
300 | pReceptionData->ModemState = pMsgData[12]; | ||
301 | pReceptionData->SNR = pMsgData[1]; | ||
302 | pReceptionData->BER = pMsgData[13]; | ||
303 | pReceptionData->RSSI = pMsgData[14]; | ||
304 | CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); | ||
305 | |||
306 | pReceptionData->InBandPwr = (s32) pMsgData[2]; | ||
307 | pReceptionData->CarrierOffset = (s32) pMsgData[15]; | ||
308 | pReceptionData->TotalTSPackets = pMsgData[3]; | ||
309 | pReceptionData->ErrorTSPackets = pMsgData[4]; | ||
310 | |||
311 | /* TS PER */ | ||
312 | if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) | ||
313 | > 0) { | ||
314 | pReceptionData->TS_PER = (SignalStatusData.etsPackets | ||
315 | * 100) / (SignalStatusData.tsPackets | ||
316 | + SignalStatusData.etsPackets); | ||
317 | } else { | ||
318 | pReceptionData->TS_PER = 0; | ||
319 | } | ||
320 | |||
321 | pReceptionData->BERBitCount = pMsgData[18]; | ||
322 | pReceptionData->BERErrorCount = pMsgData[19]; | ||
323 | |||
324 | pReceptionData->MRC_SNR = pMsgData[20]; | ||
325 | pReceptionData->MRC_InBandPwr = pMsgData[21]; | ||
326 | pReceptionData->MRC_RSSI = pMsgData[22]; | ||
327 | |||
328 | is_status_update = true; | ||
329 | break; | ||
330 | } | ||
331 | case MSG_SMS_GET_STATISTICS_RES: { | ||
332 | union { | ||
333 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt; | ||
334 | struct SmsMsgStatisticsInfo_ST dvb; | ||
335 | } *p = (void *) (phdr + 1); | ||
336 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
337 | &client->sms_stat_dvb.ReceptionData; | ||
338 | |||
339 | sms_info("MSG_SMS_GET_STATISTICS_RES"); | ||
340 | |||
341 | is_status_update = true; | ||
342 | |||
343 | switch (smscore_get_device_mode(client->coredev)) { | ||
344 | case DEVICE_MODE_ISDBT: | ||
345 | case DEVICE_MODE_ISDBT_BDA: | ||
346 | smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt); | ||
347 | break; | ||
348 | default: | ||
349 | smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat); | ||
350 | } | ||
351 | if (!pReceptionData->IsDemodLocked) { | ||
352 | pReceptionData->SNR = 0; | ||
353 | pReceptionData->BER = 0; | ||
354 | pReceptionData->BERErrorCount = 0; | ||
355 | pReceptionData->InBandPwr = 0; | ||
356 | pReceptionData->ErrorTSPackets = 0; | ||
357 | } | ||
358 | |||
359 | complete(&client->tune_done); | ||
360 | break; | ||
361 | } | ||
362 | default: | ||
363 | sms_info("Unhandled message %d", phdr->msgType); | ||
364 | |||
365 | } | ||
366 | smscore_putbuffer(client->coredev, cb); | ||
367 | |||
368 | if (is_status_update) { | ||
369 | if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { | ||
370 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | ||
371 | | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
372 | sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); | ||
373 | if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets | ||
374 | == 0) | ||
375 | sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); | ||
376 | else | ||
377 | sms_board_dvb3_event(client, | ||
378 | DVB3_EVENT_UNC_ERR); | ||
379 | |||
380 | } else { | ||
381 | if (client->sms_stat_dvb.ReceptionData.IsRfLocked) | ||
382 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
383 | else | ||
384 | client->fe_status = 0; | ||
385 | sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static void smsdvb_unregister_client(struct smsdvb_client_t *client) | ||
393 | { | ||
394 | /* must be called under clientslock */ | ||
395 | |||
396 | list_del(&client->entry); | ||
397 | |||
398 | smscore_unregister_client(client->smsclient); | ||
399 | dvb_unregister_frontend(&client->frontend); | ||
400 | dvb_dmxdev_release(&client->dmxdev); | ||
401 | dvb_dmx_release(&client->demux); | ||
402 | dvb_unregister_adapter(&client->adapter); | ||
403 | kfree(client); | ||
404 | } | ||
405 | |||
406 | static void smsdvb_onremove(void *context) | ||
407 | { | ||
408 | kmutex_lock(&g_smsdvb_clientslock); | ||
409 | |||
410 | smsdvb_unregister_client((struct smsdvb_client_t *) context); | ||
411 | |||
412 | kmutex_unlock(&g_smsdvb_clientslock); | ||
413 | } | ||
414 | |||
415 | static int smsdvb_start_feed(struct dvb_demux_feed *feed) | ||
416 | { | ||
417 | struct smsdvb_client_t *client = | ||
418 | container_of(feed->demux, struct smsdvb_client_t, demux); | ||
419 | struct SmsMsgData_ST PidMsg; | ||
420 | |||
421 | sms_debug("add pid %d(%x)", | ||
422 | feed->pid, feed->pid); | ||
423 | |||
424 | PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
425 | PidMsg.xMsgHeader.msgDstId = HIF_TASK; | ||
426 | PidMsg.xMsgHeader.msgFlags = 0; | ||
427 | PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ; | ||
428 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); | ||
429 | PidMsg.msgData[0] = feed->pid; | ||
430 | |||
431 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); | ||
432 | return smsclient_sendrequest(client->smsclient, | ||
433 | &PidMsg, sizeof(PidMsg)); | ||
434 | } | ||
435 | |||
436 | static int smsdvb_stop_feed(struct dvb_demux_feed *feed) | ||
437 | { | ||
438 | struct smsdvb_client_t *client = | ||
439 | container_of(feed->demux, struct smsdvb_client_t, demux); | ||
440 | struct SmsMsgData_ST PidMsg; | ||
441 | |||
442 | sms_debug("remove pid %d(%x)", | ||
443 | feed->pid, feed->pid); | ||
444 | |||
445 | PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
446 | PidMsg.xMsgHeader.msgDstId = HIF_TASK; | ||
447 | PidMsg.xMsgHeader.msgFlags = 0; | ||
448 | PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ; | ||
449 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); | ||
450 | PidMsg.msgData[0] = feed->pid; | ||
451 | |||
452 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); | ||
453 | return smsclient_sendrequest(client->smsclient, | ||
454 | &PidMsg, sizeof(PidMsg)); | ||
455 | } | ||
456 | |||
457 | static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, | ||
458 | void *buffer, size_t size, | ||
459 | struct completion *completion) | ||
460 | { | ||
461 | int rc; | ||
462 | |||
463 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer); | ||
464 | rc = smsclient_sendrequest(client->smsclient, buffer, size); | ||
465 | if (rc < 0) | ||
466 | return rc; | ||
467 | |||
468 | return wait_for_completion_timeout(completion, | ||
469 | msecs_to_jiffies(2000)) ? | ||
470 | 0 : -ETIME; | ||
471 | } | ||
472 | |||
473 | static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) | ||
474 | { | ||
475 | int rc; | ||
476 | struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, | ||
477 | DVBT_BDA_CONTROL_MSG_ID, | ||
478 | HIF_TASK, | ||
479 | sizeof(struct SmsMsgHdr_ST), 0 }; | ||
480 | |||
481 | rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
482 | &client->tune_done); | ||
483 | |||
484 | return rc; | ||
485 | } | ||
486 | |||
487 | static inline int led_feedback(struct smsdvb_client_t *client) | ||
488 | { | ||
489 | if (client->fe_status & FE_HAS_LOCK) | ||
490 | return sms_board_led_feedback(client->coredev, | ||
491 | (client->sms_stat_dvb.ReceptionData.BER | ||
492 | == 0) ? SMS_LED_HI : SMS_LED_LO); | ||
493 | else | ||
494 | return sms_board_led_feedback(client->coredev, SMS_LED_OFF); | ||
495 | } | ||
496 | |||
497 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
498 | { | ||
499 | int rc; | ||
500 | struct smsdvb_client_t *client; | ||
501 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
502 | |||
503 | rc = smsdvb_send_statistics_request(client); | ||
504 | |||
505 | *stat = client->fe_status; | ||
506 | |||
507 | led_feedback(client); | ||
508 | |||
509 | return rc; | ||
510 | } | ||
511 | |||
512 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
513 | { | ||
514 | int rc; | ||
515 | struct smsdvb_client_t *client; | ||
516 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
517 | |||
518 | rc = smsdvb_send_statistics_request(client); | ||
519 | |||
520 | *ber = client->sms_stat_dvb.ReceptionData.BER; | ||
521 | |||
522 | led_feedback(client); | ||
523 | |||
524 | return rc; | ||
525 | } | ||
526 | |||
527 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
528 | { | ||
529 | int rc; | ||
530 | |||
531 | struct smsdvb_client_t *client; | ||
532 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
533 | |||
534 | rc = smsdvb_send_statistics_request(client); | ||
535 | |||
536 | if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) | ||
537 | *strength = 0; | ||
538 | else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) | ||
539 | *strength = 100; | ||
540 | else | ||
541 | *strength = | ||
542 | (client->sms_stat_dvb.ReceptionData.InBandPwr | ||
543 | + 95) * 3 / 2; | ||
544 | |||
545 | led_feedback(client); | ||
546 | |||
547 | return rc; | ||
548 | } | ||
549 | |||
550 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
551 | { | ||
552 | int rc; | ||
553 | struct smsdvb_client_t *client; | ||
554 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
555 | |||
556 | rc = smsdvb_send_statistics_request(client); | ||
557 | |||
558 | *snr = client->sms_stat_dvb.ReceptionData.SNR; | ||
559 | |||
560 | led_feedback(client); | ||
561 | |||
562 | return rc; | ||
563 | } | ||
564 | |||
565 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
566 | { | ||
567 | int rc; | ||
568 | struct smsdvb_client_t *client; | ||
569 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
570 | |||
571 | rc = smsdvb_send_statistics_request(client); | ||
572 | |||
573 | *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; | ||
574 | |||
575 | led_feedback(client); | ||
576 | |||
577 | return rc; | ||
578 | } | ||
579 | |||
580 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, | ||
581 | struct dvb_frontend_tune_settings *tune) | ||
582 | { | ||
583 | sms_debug(""); | ||
584 | |||
585 | tune->min_delay_ms = 400; | ||
586 | tune->step_size = 250000; | ||
587 | tune->max_drift = 0; | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe) | ||
592 | { | ||
593 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
594 | struct smsdvb_client_t *client = | ||
595 | container_of(fe, struct smsdvb_client_t, frontend); | ||
596 | |||
597 | struct { | ||
598 | struct SmsMsgHdr_ST Msg; | ||
599 | u32 Data[3]; | ||
600 | } Msg; | ||
601 | |||
602 | int ret; | ||
603 | |||
604 | client->fe_status = FE_HAS_SIGNAL; | ||
605 | client->event_fe_state = -1; | ||
606 | client->event_unc_state = -1; | ||
607 | fe->dtv_property_cache.delivery_system = SYS_DVBT; | ||
608 | |||
609 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
610 | Msg.Msg.msgDstId = HIF_TASK; | ||
611 | Msg.Msg.msgFlags = 0; | ||
612 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | ||
613 | Msg.Msg.msgLength = sizeof(Msg); | ||
614 | Msg.Data[0] = c->frequency; | ||
615 | Msg.Data[2] = 12000000; | ||
616 | |||
617 | sms_info("%s: freq %d band %d", __func__, c->frequency, | ||
618 | c->bandwidth_hz); | ||
619 | |||
620 | switch (c->bandwidth_hz / 1000000) { | ||
621 | case 8: | ||
622 | Msg.Data[1] = BW_8_MHZ; | ||
623 | break; | ||
624 | case 7: | ||
625 | Msg.Data[1] = BW_7_MHZ; | ||
626 | break; | ||
627 | case 6: | ||
628 | Msg.Data[1] = BW_6_MHZ; | ||
629 | break; | ||
630 | case 0: | ||
631 | return -EOPNOTSUPP; | ||
632 | default: | ||
633 | return -EINVAL; | ||
634 | } | ||
635 | /* Disable LNA, if any. An error is returned if no LNA is present */ | ||
636 | ret = sms_board_lna_control(client->coredev, 0); | ||
637 | if (ret == 0) { | ||
638 | fe_status_t status; | ||
639 | |||
640 | /* tune with LNA off at first */ | ||
641 | ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
642 | &client->tune_done); | ||
643 | |||
644 | smsdvb_read_status(fe, &status); | ||
645 | |||
646 | if (status & FE_HAS_LOCK) | ||
647 | return ret; | ||
648 | |||
649 | /* previous tune didn't lock - enable LNA and tune again */ | ||
650 | sms_board_lna_control(client->coredev, 1); | ||
651 | } | ||
652 | |||
653 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
654 | &client->tune_done); | ||
655 | } | ||
656 | |||
657 | static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe) | ||
658 | { | ||
659 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
660 | struct smsdvb_client_t *client = | ||
661 | container_of(fe, struct smsdvb_client_t, frontend); | ||
662 | |||
663 | struct { | ||
664 | struct SmsMsgHdr_ST Msg; | ||
665 | u32 Data[4]; | ||
666 | } Msg; | ||
667 | |||
668 | fe->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
669 | |||
670 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
671 | Msg.Msg.msgDstId = HIF_TASK; | ||
672 | Msg.Msg.msgFlags = 0; | ||
673 | Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ; | ||
674 | Msg.Msg.msgLength = sizeof(Msg); | ||
675 | |||
676 | if (c->isdbt_sb_segment_idx == -1) | ||
677 | c->isdbt_sb_segment_idx = 0; | ||
678 | |||
679 | switch (c->isdbt_sb_segment_count) { | ||
680 | case 3: | ||
681 | Msg.Data[1] = BW_ISDBT_3SEG; | ||
682 | break; | ||
683 | case 1: | ||
684 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
685 | break; | ||
686 | case 0: /* AUTO */ | ||
687 | switch (c->bandwidth_hz / 1000000) { | ||
688 | case 8: | ||
689 | case 7: | ||
690 | c->isdbt_sb_segment_count = 3; | ||
691 | Msg.Data[1] = BW_ISDBT_3SEG; | ||
692 | break; | ||
693 | case 6: | ||
694 | c->isdbt_sb_segment_count = 1; | ||
695 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
696 | break; | ||
697 | default: /* Assumes 6 MHZ bw */ | ||
698 | c->isdbt_sb_segment_count = 1; | ||
699 | c->bandwidth_hz = 6000; | ||
700 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
701 | break; | ||
702 | } | ||
703 | break; | ||
704 | default: | ||
705 | sms_info("Segment count %d not supported", c->isdbt_sb_segment_count); | ||
706 | return -EINVAL; | ||
707 | } | ||
708 | |||
709 | Msg.Data[0] = c->frequency; | ||
710 | Msg.Data[2] = 12000000; | ||
711 | Msg.Data[3] = c->isdbt_sb_segment_idx; | ||
712 | |||
713 | sms_info("%s: freq %d segwidth %d segindex %d\n", __func__, | ||
714 | c->frequency, c->isdbt_sb_segment_count, | ||
715 | c->isdbt_sb_segment_idx); | ||
716 | |||
717 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
718 | &client->tune_done); | ||
719 | } | ||
720 | |||
721 | static int smsdvb_set_frontend(struct dvb_frontend *fe) | ||
722 | { | ||
723 | struct smsdvb_client_t *client = | ||
724 | container_of(fe, struct smsdvb_client_t, frontend); | ||
725 | struct smscore_device_t *coredev = client->coredev; | ||
726 | |||
727 | switch (smscore_get_device_mode(coredev)) { | ||
728 | case DEVICE_MODE_DVBT: | ||
729 | case DEVICE_MODE_DVBT_BDA: | ||
730 | return smsdvb_dvbt_set_frontend(fe); | ||
731 | case DEVICE_MODE_ISDBT: | ||
732 | case DEVICE_MODE_ISDBT_BDA: | ||
733 | return smsdvb_isdbt_set_frontend(fe); | ||
734 | default: | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | static int smsdvb_get_frontend(struct dvb_frontend *fe) | ||
740 | { | ||
741 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; | ||
742 | struct smsdvb_client_t *client = | ||
743 | container_of(fe, struct smsdvb_client_t, frontend); | ||
744 | struct smscore_device_t *coredev = client->coredev; | ||
745 | struct TRANSMISSION_STATISTICS_S *td = | ||
746 | &client->sms_stat_dvb.TransmissionData; | ||
747 | |||
748 | switch (smscore_get_device_mode(coredev)) { | ||
749 | case DEVICE_MODE_DVBT: | ||
750 | case DEVICE_MODE_DVBT_BDA: | ||
751 | fep->frequency = td->Frequency; | ||
752 | |||
753 | switch (td->Bandwidth) { | ||
754 | case 6: | ||
755 | fep->bandwidth_hz = 6000000; | ||
756 | break; | ||
757 | case 7: | ||
758 | fep->bandwidth_hz = 7000000; | ||
759 | break; | ||
760 | case 8: | ||
761 | fep->bandwidth_hz = 8000000; | ||
762 | break; | ||
763 | } | ||
764 | |||
765 | switch (td->TransmissionMode) { | ||
766 | case 2: | ||
767 | fep->transmission_mode = TRANSMISSION_MODE_2K; | ||
768 | break; | ||
769 | case 8: | ||
770 | fep->transmission_mode = TRANSMISSION_MODE_8K; | ||
771 | } | ||
772 | |||
773 | switch (td->GuardInterval) { | ||
774 | case 0: | ||
775 | fep->guard_interval = GUARD_INTERVAL_1_32; | ||
776 | break; | ||
777 | case 1: | ||
778 | fep->guard_interval = GUARD_INTERVAL_1_16; | ||
779 | break; | ||
780 | case 2: | ||
781 | fep->guard_interval = GUARD_INTERVAL_1_8; | ||
782 | break; | ||
783 | case 3: | ||
784 | fep->guard_interval = GUARD_INTERVAL_1_4; | ||
785 | break; | ||
786 | } | ||
787 | |||
788 | switch (td->CodeRate) { | ||
789 | case 0: | ||
790 | fep->code_rate_HP = FEC_1_2; | ||
791 | break; | ||
792 | case 1: | ||
793 | fep->code_rate_HP = FEC_2_3; | ||
794 | break; | ||
795 | case 2: | ||
796 | fep->code_rate_HP = FEC_3_4; | ||
797 | break; | ||
798 | case 3: | ||
799 | fep->code_rate_HP = FEC_5_6; | ||
800 | break; | ||
801 | case 4: | ||
802 | fep->code_rate_HP = FEC_7_8; | ||
803 | break; | ||
804 | } | ||
805 | |||
806 | switch (td->LPCodeRate) { | ||
807 | case 0: | ||
808 | fep->code_rate_LP = FEC_1_2; | ||
809 | break; | ||
810 | case 1: | ||
811 | fep->code_rate_LP = FEC_2_3; | ||
812 | break; | ||
813 | case 2: | ||
814 | fep->code_rate_LP = FEC_3_4; | ||
815 | break; | ||
816 | case 3: | ||
817 | fep->code_rate_LP = FEC_5_6; | ||
818 | break; | ||
819 | case 4: | ||
820 | fep->code_rate_LP = FEC_7_8; | ||
821 | break; | ||
822 | } | ||
823 | |||
824 | switch (td->Constellation) { | ||
825 | case 0: | ||
826 | fep->modulation = QPSK; | ||
827 | break; | ||
828 | case 1: | ||
829 | fep->modulation = QAM_16; | ||
830 | break; | ||
831 | case 2: | ||
832 | fep->modulation = QAM_64; | ||
833 | break; | ||
834 | } | ||
835 | |||
836 | switch (td->Hierarchy) { | ||
837 | case 0: | ||
838 | fep->hierarchy = HIERARCHY_NONE; | ||
839 | break; | ||
840 | case 1: | ||
841 | fep->hierarchy = HIERARCHY_1; | ||
842 | break; | ||
843 | case 2: | ||
844 | fep->hierarchy = HIERARCHY_2; | ||
845 | break; | ||
846 | case 3: | ||
847 | fep->hierarchy = HIERARCHY_4; | ||
848 | break; | ||
849 | } | ||
850 | |||
851 | fep->inversion = INVERSION_AUTO; | ||
852 | break; | ||
853 | case DEVICE_MODE_ISDBT: | ||
854 | case DEVICE_MODE_ISDBT_BDA: | ||
855 | fep->frequency = td->Frequency; | ||
856 | fep->bandwidth_hz = 6000000; | ||
857 | /* todo: retrive the other parameters */ | ||
858 | break; | ||
859 | default: | ||
860 | return -EINVAL; | ||
861 | } | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int smsdvb_init(struct dvb_frontend *fe) | ||
867 | { | ||
868 | struct smsdvb_client_t *client = | ||
869 | container_of(fe, struct smsdvb_client_t, frontend); | ||
870 | |||
871 | sms_board_power(client->coredev, 1); | ||
872 | |||
873 | sms_board_dvb3_event(client, DVB3_EVENT_INIT); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int smsdvb_sleep(struct dvb_frontend *fe) | ||
878 | { | ||
879 | struct smsdvb_client_t *client = | ||
880 | container_of(fe, struct smsdvb_client_t, frontend); | ||
881 | |||
882 | sms_board_led_feedback(client->coredev, SMS_LED_OFF); | ||
883 | sms_board_power(client->coredev, 0); | ||
884 | |||
885 | sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | static void smsdvb_release(struct dvb_frontend *fe) | ||
891 | { | ||
892 | /* do nothing */ | ||
893 | } | ||
894 | |||
895 | static struct dvb_frontend_ops smsdvb_fe_ops = { | ||
896 | .info = { | ||
897 | .name = "Siano Mobile Digital MDTV Receiver", | ||
898 | .frequency_min = 44250000, | ||
899 | .frequency_max = 867250000, | ||
900 | .frequency_stepsize = 250000, | ||
901 | .caps = FE_CAN_INVERSION_AUTO | | ||
902 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
903 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
904 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
905 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
906 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
907 | FE_CAN_RECOVER | | ||
908 | FE_CAN_HIERARCHY_AUTO, | ||
909 | }, | ||
910 | |||
911 | .release = smsdvb_release, | ||
912 | |||
913 | .set_frontend = smsdvb_set_frontend, | ||
914 | .get_frontend = smsdvb_get_frontend, | ||
915 | .get_tune_settings = smsdvb_get_tune_settings, | ||
916 | |||
917 | .read_status = smsdvb_read_status, | ||
918 | .read_ber = smsdvb_read_ber, | ||
919 | .read_signal_strength = smsdvb_read_signal_strength, | ||
920 | .read_snr = smsdvb_read_snr, | ||
921 | .read_ucblocks = smsdvb_read_ucblocks, | ||
922 | |||
923 | .init = smsdvb_init, | ||
924 | .sleep = smsdvb_sleep, | ||
925 | }; | ||
926 | |||
927 | static int smsdvb_hotplug(struct smscore_device_t *coredev, | ||
928 | struct device *device, int arrival) | ||
929 | { | ||
930 | struct smsclient_params_t params; | ||
931 | struct smsdvb_client_t *client; | ||
932 | int rc; | ||
933 | |||
934 | /* device removal handled by onremove callback */ | ||
935 | if (!arrival) | ||
936 | return 0; | ||
937 | client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); | ||
938 | if (!client) { | ||
939 | sms_err("kmalloc() failed"); | ||
940 | return -ENOMEM; | ||
941 | } | ||
942 | |||
943 | /* register dvb adapter */ | ||
944 | rc = dvb_register_adapter(&client->adapter, | ||
945 | sms_get_board( | ||
946 | smscore_get_board_id(coredev))->name, | ||
947 | THIS_MODULE, device, adapter_nr); | ||
948 | if (rc < 0) { | ||
949 | sms_err("dvb_register_adapter() failed %d", rc); | ||
950 | goto adapter_error; | ||
951 | } | ||
952 | |||
953 | /* init dvb demux */ | ||
954 | client->demux.dmx.capabilities = DMX_TS_FILTERING; | ||
955 | client->demux.filternum = 32; /* todo: nova ??? */ | ||
956 | client->demux.feednum = 32; | ||
957 | client->demux.start_feed = smsdvb_start_feed; | ||
958 | client->demux.stop_feed = smsdvb_stop_feed; | ||
959 | |||
960 | rc = dvb_dmx_init(&client->demux); | ||
961 | if (rc < 0) { | ||
962 | sms_err("dvb_dmx_init failed %d", rc); | ||
963 | goto dvbdmx_error; | ||
964 | } | ||
965 | |||
966 | /* init dmxdev */ | ||
967 | client->dmxdev.filternum = 32; | ||
968 | client->dmxdev.demux = &client->demux.dmx; | ||
969 | client->dmxdev.capabilities = 0; | ||
970 | |||
971 | rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); | ||
972 | if (rc < 0) { | ||
973 | sms_err("dvb_dmxdev_init failed %d", rc); | ||
974 | goto dmxdev_error; | ||
975 | } | ||
976 | |||
977 | /* init and register frontend */ | ||
978 | memcpy(&client->frontend.ops, &smsdvb_fe_ops, | ||
979 | sizeof(struct dvb_frontend_ops)); | ||
980 | |||
981 | switch (smscore_get_device_mode(coredev)) { | ||
982 | case DEVICE_MODE_DVBT: | ||
983 | case DEVICE_MODE_DVBT_BDA: | ||
984 | client->frontend.ops.delsys[0] = SYS_DVBT; | ||
985 | break; | ||
986 | case DEVICE_MODE_ISDBT: | ||
987 | case DEVICE_MODE_ISDBT_BDA: | ||
988 | client->frontend.ops.delsys[0] = SYS_ISDBT; | ||
989 | break; | ||
990 | } | ||
991 | |||
992 | rc = dvb_register_frontend(&client->adapter, &client->frontend); | ||
993 | if (rc < 0) { | ||
994 | sms_err("frontend registration failed %d", rc); | ||
995 | goto frontend_error; | ||
996 | } | ||
997 | |||
998 | params.initial_id = 1; | ||
999 | params.data_type = MSG_SMS_DVBT_BDA_DATA; | ||
1000 | params.onresponse_handler = smsdvb_onresponse; | ||
1001 | params.onremove_handler = smsdvb_onremove; | ||
1002 | params.context = client; | ||
1003 | |||
1004 | rc = smscore_register_client(coredev, ¶ms, &client->smsclient); | ||
1005 | if (rc < 0) { | ||
1006 | sms_err("smscore_register_client() failed %d", rc); | ||
1007 | goto client_error; | ||
1008 | } | ||
1009 | |||
1010 | client->coredev = coredev; | ||
1011 | |||
1012 | init_completion(&client->tune_done); | ||
1013 | |||
1014 | kmutex_lock(&g_smsdvb_clientslock); | ||
1015 | |||
1016 | list_add(&client->entry, &g_smsdvb_clients); | ||
1017 | |||
1018 | kmutex_unlock(&g_smsdvb_clientslock); | ||
1019 | |||
1020 | client->event_fe_state = -1; | ||
1021 | client->event_unc_state = -1; | ||
1022 | sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); | ||
1023 | |||
1024 | sms_info("success"); | ||
1025 | sms_board_setup(coredev); | ||
1026 | |||
1027 | return 0; | ||
1028 | |||
1029 | client_error: | ||
1030 | dvb_unregister_frontend(&client->frontend); | ||
1031 | |||
1032 | frontend_error: | ||
1033 | dvb_dmxdev_release(&client->dmxdev); | ||
1034 | |||
1035 | dmxdev_error: | ||
1036 | dvb_dmx_release(&client->demux); | ||
1037 | |||
1038 | dvbdmx_error: | ||
1039 | dvb_unregister_adapter(&client->adapter); | ||
1040 | |||
1041 | adapter_error: | ||
1042 | kfree(client); | ||
1043 | return rc; | ||
1044 | } | ||
1045 | |||
1046 | static int __init smsdvb_module_init(void) | ||
1047 | { | ||
1048 | int rc; | ||
1049 | |||
1050 | INIT_LIST_HEAD(&g_smsdvb_clients); | ||
1051 | kmutex_init(&g_smsdvb_clientslock); | ||
1052 | |||
1053 | rc = smscore_register_hotplug(smsdvb_hotplug); | ||
1054 | |||
1055 | sms_debug(""); | ||
1056 | |||
1057 | return rc; | ||
1058 | } | ||
1059 | |||
1060 | static void __exit smsdvb_module_exit(void) | ||
1061 | { | ||
1062 | smscore_unregister_hotplug(smsdvb_hotplug); | ||
1063 | |||
1064 | kmutex_lock(&g_smsdvb_clientslock); | ||
1065 | |||
1066 | while (!list_empty(&g_smsdvb_clients)) | ||
1067 | smsdvb_unregister_client( | ||
1068 | (struct smsdvb_client_t *) g_smsdvb_clients.next); | ||
1069 | |||
1070 | kmutex_unlock(&g_smsdvb_clientslock); | ||
1071 | } | ||
1072 | |||
1073 | module_init(smsdvb_module_init); | ||
1074 | module_exit(smsdvb_module_exit); | ||
1075 | |||
1076 | MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); | ||
1077 | MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); | ||
1078 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/siano/smsendian.c b/drivers/media/common/siano/smsendian.c deleted file mode 100644 index e2657c2f010..00000000000 --- a/drivers/media/common/siano/smsendian.c +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #include <linux/export.h> | ||
23 | #include <asm/byteorder.h> | ||
24 | |||
25 | #include "smsendian.h" | ||
26 | #include "smscoreapi.h" | ||
27 | |||
28 | void smsendian_handle_tx_message(void *buffer) | ||
29 | { | ||
30 | #ifdef __BIG_ENDIAN | ||
31 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; | ||
32 | int i; | ||
33 | int msgWords; | ||
34 | |||
35 | switch (msg->xMsgHeader.msgType) { | ||
36 | case MSG_SMS_DATA_DOWNLOAD_REQ: | ||
37 | { | ||
38 | msg->msgData[0] = le32_to_cpu(msg->msgData[0]); | ||
39 | break; | ||
40 | } | ||
41 | |||
42 | default: | ||
43 | msgWords = (msg->xMsgHeader.msgLength - | ||
44 | sizeof(struct SmsMsgHdr_ST))/4; | ||
45 | |||
46 | for (i = 0; i < msgWords; i++) | ||
47 | msg->msgData[i] = le32_to_cpu(msg->msgData[i]); | ||
48 | |||
49 | break; | ||
50 | } | ||
51 | #endif /* __BIG_ENDIAN */ | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(smsendian_handle_tx_message); | ||
54 | |||
55 | void smsendian_handle_rx_message(void *buffer) | ||
56 | { | ||
57 | #ifdef __BIG_ENDIAN | ||
58 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; | ||
59 | int i; | ||
60 | int msgWords; | ||
61 | |||
62 | switch (msg->xMsgHeader.msgType) { | ||
63 | case MSG_SMS_GET_VERSION_EX_RES: | ||
64 | { | ||
65 | struct SmsVersionRes_ST *ver = | ||
66 | (struct SmsVersionRes_ST *) msg; | ||
67 | ver->ChipModel = le16_to_cpu(ver->ChipModel); | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | case MSG_SMS_DVBT_BDA_DATA: | ||
72 | case MSG_SMS_DAB_CHANNEL: | ||
73 | case MSG_SMS_DATA_MSG: | ||
74 | { | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | default: | ||
79 | { | ||
80 | msgWords = (msg->xMsgHeader.msgLength - | ||
81 | sizeof(struct SmsMsgHdr_ST))/4; | ||
82 | |||
83 | for (i = 0; i < msgWords; i++) | ||
84 | msg->msgData[i] = le32_to_cpu(msg->msgData[i]); | ||
85 | |||
86 | break; | ||
87 | } | ||
88 | } | ||
89 | #endif /* __BIG_ENDIAN */ | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(smsendian_handle_rx_message); | ||
92 | |||
93 | void smsendian_handle_message_header(void *msg) | ||
94 | { | ||
95 | #ifdef __BIG_ENDIAN | ||
96 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg; | ||
97 | |||
98 | phdr->msgType = le16_to_cpu(phdr->msgType); | ||
99 | phdr->msgLength = le16_to_cpu(phdr->msgLength); | ||
100 | phdr->msgFlags = le16_to_cpu(phdr->msgFlags); | ||
101 | #endif /* __BIG_ENDIAN */ | ||
102 | } | ||
103 | EXPORT_SYMBOL_GPL(smsendian_handle_message_header); | ||
diff --git a/drivers/media/common/siano/smsendian.h b/drivers/media/common/siano/smsendian.h deleted file mode 100644 index 1624d6fd367..00000000000 --- a/drivers/media/common/siano/smsendian.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #ifndef __SMS_ENDIAN_H__ | ||
23 | #define __SMS_ENDIAN_H__ | ||
24 | |||
25 | #include <asm/byteorder.h> | ||
26 | |||
27 | extern void smsendian_handle_tx_message(void *buffer); | ||
28 | extern void smsendian_handle_rx_message(void *buffer); | ||
29 | extern void smsendian_handle_message_header(void *msg); | ||
30 | |||
31 | #endif /* __SMS_ENDIAN_H__ */ | ||
32 | |||
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c deleted file mode 100644 index b8c5cad7853..00000000000 --- a/drivers/media/common/siano/smsir.c +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | Copyright (c) 2010 - Mauro Carvalho Chehab | ||
8 | - Ported the driver to use rc-core | ||
9 | - IR raw event decoding is now done at rc-core | ||
10 | - Code almost re-written | ||
11 | |||
12 | This program is free software: you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation, either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
24 | |||
25 | ****************************************************************/ | ||
26 | |||
27 | |||
28 | #include <linux/types.h> | ||
29 | #include <linux/input.h> | ||
30 | |||
31 | #include "smscoreapi.h" | ||
32 | #include "smsir.h" | ||
33 | #include "sms-cards.h" | ||
34 | |||
35 | #define MODULE_NAME "smsmdtv" | ||
36 | |||
37 | void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) | ||
38 | { | ||
39 | int i; | ||
40 | const s32 *samples = (const void *)buf; | ||
41 | |||
42 | for (i = 0; i < len >> 2; i++) { | ||
43 | DEFINE_IR_RAW_EVENT(ev); | ||
44 | |||
45 | ev.duration = abs(samples[i]) * 1000; /* Convert to ns */ | ||
46 | ev.pulse = (samples[i] > 0) ? false : true; | ||
47 | |||
48 | ir_raw_event_store(coredev->ir.dev, &ev); | ||
49 | } | ||
50 | ir_raw_event_handle(coredev->ir.dev); | ||
51 | } | ||
52 | |||
53 | int sms_ir_init(struct smscore_device_t *coredev) | ||
54 | { | ||
55 | int err; | ||
56 | int board_id = smscore_get_board_id(coredev); | ||
57 | struct rc_dev *dev; | ||
58 | |||
59 | sms_log("Allocating rc device"); | ||
60 | dev = rc_allocate_device(); | ||
61 | if (!dev) { | ||
62 | sms_err("Not enough memory"); | ||
63 | return -ENOMEM; | ||
64 | } | ||
65 | |||
66 | coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ | ||
67 | coredev->ir.timeout = IR_DEFAULT_TIMEOUT; | ||
68 | sms_log("IR port %d, timeout %d ms", | ||
69 | coredev->ir.controller, coredev->ir.timeout); | ||
70 | |||
71 | snprintf(coredev->ir.name, sizeof(coredev->ir.name), | ||
72 | "SMS IR (%s)", sms_get_board(board_id)->name); | ||
73 | |||
74 | strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); | ||
75 | strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); | ||
76 | |||
77 | dev->input_name = coredev->ir.name; | ||
78 | dev->input_phys = coredev->ir.phys; | ||
79 | dev->dev.parent = coredev->device; | ||
80 | |||
81 | #if 0 | ||
82 | /* TODO: properly initialize the parameters bellow */ | ||
83 | dev->input_id.bustype = BUS_USB; | ||
84 | dev->input_id.version = 1; | ||
85 | dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); | ||
86 | dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
87 | #endif | ||
88 | |||
89 | dev->priv = coredev; | ||
90 | dev->driver_type = RC_DRIVER_IR_RAW; | ||
91 | dev->allowed_protos = RC_BIT_ALL; | ||
92 | dev->map_name = sms_get_board(board_id)->rc_codes; | ||
93 | dev->driver_name = MODULE_NAME; | ||
94 | |||
95 | sms_log("Input device (IR) %s is set for key events", dev->input_name); | ||
96 | |||
97 | err = rc_register_device(dev); | ||
98 | if (err < 0) { | ||
99 | sms_err("Failed to register device"); | ||
100 | rc_free_device(dev); | ||
101 | return err; | ||
102 | } | ||
103 | |||
104 | coredev->ir.dev = dev; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | void sms_ir_exit(struct smscore_device_t *coredev) | ||
109 | { | ||
110 | if (coredev->ir.dev) | ||
111 | rc_unregister_device(coredev->ir.dev); | ||
112 | |||
113 | sms_log(""); | ||
114 | } | ||
diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h deleted file mode 100644 index 69b59b9eee2..00000000000 --- a/drivers/media/common/siano/smsir.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | Copyright (c) 2010 - Mauro Carvalho Chehab | ||
8 | - Ported the driver to use rc-core | ||
9 | - IR raw event decoding is now done at rc-core | ||
10 | - Code almost re-written | ||
11 | |||
12 | This program is free software: you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation, either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
24 | |||
25 | ****************************************************************/ | ||
26 | |||
27 | #ifndef __SMS_IR_H__ | ||
28 | #define __SMS_IR_H__ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | #include <media/rc-core.h> | ||
32 | |||
33 | #define IR_DEFAULT_TIMEOUT 100 | ||
34 | |||
35 | struct smscore_device_t; | ||
36 | |||
37 | struct ir_t { | ||
38 | struct rc_dev *dev; | ||
39 | char name[40]; | ||
40 | char phys[32]; | ||
41 | |||
42 | char *rc_codes; | ||
43 | u64 protocol; | ||
44 | |||
45 | u32 timeout; | ||
46 | u32 controller; | ||
47 | }; | ||
48 | |||
49 | #ifdef CONFIG_SMS_SIANO_RC | ||
50 | int sms_ir_init(struct smscore_device_t *coredev); | ||
51 | void sms_ir_exit(struct smscore_device_t *coredev); | ||
52 | void sms_ir_event(struct smscore_device_t *coredev, | ||
53 | const char *buf, int len); | ||
54 | #else | ||
55 | inline static int sms_ir_init(struct smscore_device_t *coredev) { | ||
56 | return 0; | ||
57 | } | ||
58 | inline static void sms_ir_exit(struct smscore_device_t *coredev) {}; | ||
59 | inline static void sms_ir_event(struct smscore_device_t *coredev, | ||
60 | const char *buf, int len) {}; | ||
61 | #endif | ||
62 | |||
63 | #endif /* __SMS_IR_H__ */ | ||
64 | |||