aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPierrick Hascoet <pierrick.hascoet@abilis.com>2011-10-31 11:24:39 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-03 05:42:49 -0400
commit41b44e0418112e694f9b7beb8088efbb8c9c0053 (patch)
treec12811c8a738b48f75d8b9a9eeb7e7d1cad68a54 /drivers
parent539b469518b45c0b5915bec3e258e21e03667084 (diff)
[media] staging: as102: Initial import from Abilis
Changes by Devin Heitmueller: Import the original Abilis Systems as102 driver. The source is unmodified, with the only changes I've made so far were that I created a Kconfig and Makefile so that the code builds in a standard v4l-dvb tree. This driver requires firmware (which Abilis has provided with redistribution terms which will allow it to be bundled in the Linux distributions). The firmware can be downloaded from here: Thanks to Rainer Miethling from PCTV Systems for working to get the driver released (for use with the PCTV 74e) and Pierrick Hascoet from Abilis for authoring the driver. Changes by Piotr Chmura: - moved the driver from media/dvb to staging/media - removed Makefile/Kconfig - compilation fails in current tree [snjw23@gmail.com: edited changelog] Signed-off-by: Pierrick Hascoet <pierrick.hascoet@abilis.com> Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Piotr Chmura <chmooreck@poczta.onet.pl> Signed-off-by: Sylwester Nawrocki <snjw23@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/media/as102/Kconfig7
-rw-r--r--drivers/staging/media/as102/Makefile5
-rw-r--r--drivers/staging/media/as102/as102_drv.c356
-rw-r--r--drivers/staging/media/as102/as102_drv.h146
-rw-r--r--drivers/staging/media/as102/as102_fe.c647
-rw-r--r--drivers/staging/media/as102/as102_fw.c236
-rw-r--r--drivers/staging/media/as102/as102_fw.h42
-rw-r--r--drivers/staging/media/as102/as102_usb_drv.c432
-rw-r--r--drivers/staging/media/as102/as102_usb_drv.h54
-rw-r--r--drivers/staging/media/as102/as10x_cmd.c478
-rw-r--r--drivers/staging/media/as102/as10x_cmd.h540
-rw-r--r--drivers/staging/media/as102/as10x_cmd_cfg.c239
-rw-r--r--drivers/staging/media/as102/as10x_cmd_stream.c256
-rw-r--r--drivers/staging/media/as102/as10x_handle.h58
-rw-r--r--drivers/staging/media/as102/as10x_types.h198
15 files changed, 3694 insertions, 0 deletions
diff --git a/drivers/staging/media/as102/Kconfig b/drivers/staging/media/as102/Kconfig
new file mode 100644
index 00000000000..5865029db0f
--- /dev/null
+++ b/drivers/staging/media/as102/Kconfig
@@ -0,0 +1,7 @@
1config DVB_AS102
2 tristate "Abilis AS102 DVB receiver"
3 depends on DVB_CORE && USB && I2C && INPUT
4 help
5 Choose Y or M here if you have a device containing an AS102
6
7 To compile this driver as a module, choose M here
diff --git a/drivers/staging/media/as102/Makefile b/drivers/staging/media/as102/Makefile
new file mode 100644
index 00000000000..c2334c6c952
--- /dev/null
+++ b/drivers/staging/media/as102/Makefile
@@ -0,0 +1,5 @@
1dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o as102_fe.o as102_usb_drv.o as10x_cmd_cfg.o
2
3obj-$(CONFIG_DVB_AS102) += dvb-as102.o
4
5EXTRA_CFLAGS += -DLINUX -DCONFIG_AS102_USB -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c
new file mode 100644
index 00000000000..c334bffa36e
--- /dev/null
+++ b/drivers/staging/media/as102/as102_drv.c
@@ -0,0 +1,356 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/slab.h>
23#include <linux/module.h>
24#include <linux/mm.h>
25#include <linux/kref.h>
26#include <asm/uaccess.h>
27#include <linux/usb.h>
28
29/* header file for Usb device driver*/
30#include "as102_drv.h"
31#include "as102_fw.h"
32
33#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
34#include "dvbdev.h"
35#else
36#warning >>> DVB_CORE not defined !!! <<<
37#endif
38
39int debug = 0;
40module_param_named(debug, debug, int, 0644);
41MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");
42
43int dual_tuner = 0;
44module_param_named(dual_tuner, dual_tuner, int, 0644);
45MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner configuration (default: off)");
46
47static int fw_upload = 1;
48module_param_named(fw_upload, fw_upload, int, 0644);
49MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");
50
51static int pid_filtering = 0;
52module_param_named(pid_filtering, pid_filtering, int, 0644);
53MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");
54
55static int ts_auto_disable = 0;
56module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
57MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");
58
59int elna_enable = 1;
60module_param_named(elna_enable, elna_enable, int, 0644);
61MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
62
63#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
64DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
65#endif
66
67#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
68static void as102_stop_stream(struct as102_dev_t *dev) {
69 struct as102_bus_adapter_t *bus_adap;
70
71 if (dev != NULL)
72 bus_adap = &dev->bus_adap;
73 else
74 return;
75
76 if (bus_adap->ops->stop_stream != NULL)
77 bus_adap->ops->stop_stream(dev);
78
79 if (ts_auto_disable) {
80 if (mutex_lock_interruptible(&dev->bus_adap.lock))
81 return;
82
83 if (as10x_cmd_stop_streaming(bus_adap) < 0) {
84 dprintk(debug, "as10x_cmd_stop_streaming failed\n");
85 }
86
87 mutex_unlock(&dev->bus_adap.lock);
88 }
89}
90
91static int as102_start_stream(struct as102_dev_t *dev) {
92
93 struct as102_bus_adapter_t *bus_adap;
94 int ret = -EFAULT;
95
96 if (dev != NULL)
97 bus_adap = &dev->bus_adap;
98 else
99 return ret;
100
101 if (bus_adap->ops->start_stream != NULL) {
102 ret = bus_adap->ops->start_stream(dev);
103 }
104
105 if (ts_auto_disable) {
106 if (mutex_lock_interruptible(&dev->bus_adap.lock))
107 return -EFAULT;
108
109 ret = as10x_cmd_start_streaming(bus_adap);
110
111 mutex_unlock(&dev->bus_adap.lock);
112 }
113
114 return ret;
115}
116
117static int as10x_pid_filter(struct as102_dev_t *dev,
118 int index, u16 pid, int onoff) {
119
120 struct as102_bus_adapter_t *bus_adap = &dev->bus_adap;
121 int ret = -EFAULT;
122
123 ENTER();
124
125 if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
126 dprintk(debug, "mutex_lock_interruptible(lock) failed !\n");
127 return -EBUSY;
128 }
129
130 switch(onoff) {
131 case 0:
132 ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
133 dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
134 index, pid, ret);
135 break;
136 case 1:
137 {
138 struct as10x_ts_filter filter;
139
140 filter.type = TS_PID_TYPE_TS;
141 filter.idx = 0xFF;
142 filter.pid = pid;
143
144 ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
145 dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
146 index, filter.idx, filter.pid, ret);
147 break;
148 }
149 }
150
151 mutex_unlock(&dev->bus_adap.lock);
152
153 LEAVE();
154 return ret;
155}
156
157static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed) {
158 int ret = 0;
159 struct dvb_demux *demux = dvbdmxfeed->demux;
160 struct as102_dev_t *as102_dev = demux->priv;
161
162 ENTER();
163
164 if (mutex_lock_interruptible(&as102_dev->sem))
165 return -ERESTARTSYS;
166
167 if (pid_filtering) {
168 as10x_pid_filter(as102_dev,
169 dvbdmxfeed->index, dvbdmxfeed->pid, 1);
170 }
171
172 if (as102_dev->streaming++ == 0) {
173 ret = as102_start_stream(as102_dev);
174 }
175
176 mutex_unlock(&as102_dev->sem);
177 LEAVE();
178 return ret;
179}
180
181static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) {
182 struct dvb_demux *demux = dvbdmxfeed->demux;
183 struct as102_dev_t *as102_dev = demux->priv;
184
185 ENTER();
186
187 if (mutex_lock_interruptible(&as102_dev->sem))
188 return -ERESTARTSYS;
189
190 if (--as102_dev->streaming == 0) {
191 as102_stop_stream(as102_dev);
192 }
193
194 if (pid_filtering) {
195 as10x_pid_filter(as102_dev,
196 dvbdmxfeed->index, dvbdmxfeed->pid, 0);
197 }
198
199 mutex_unlock(&as102_dev->sem);
200 LEAVE();
201 return 0;
202}
203#endif
204
205int as102_dvb_register(struct as102_dev_t *as102_dev) {
206 int ret = 0;
207 ENTER();
208
209#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
210 ret = dvb_register_adapter(&as102_dev->dvb_adap,
211 DEVICE_FULL_NAME,
212 THIS_MODULE,
213#if defined(CONFIG_AS102_USB)
214 &as102_dev->bus_adap.usb_dev->dev
215#elif defined(CONFIG_AS102_SPI)
216 &as102_dev->bus_adap.spi_dev->dev
217#else
218#error >>> dvb_register_adapter <<<
219#endif
220#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
221 , adapter_nr
222#endif
223 );
224 if (ret < 0) {
225 err("%s: dvb_register_adapter() failed (errno = %d)",
226 __FUNCTION__, ret);
227 goto failed;
228 }
229
230 as102_dev->dvb_dmx.priv = as102_dev;
231 as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
232 as102_dev->dvb_dmx.feednum = 256;
233 as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
234 as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;
235
236 as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
237 DMX_SECTION_FILTERING;
238
239 as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
240 as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
241 as102_dev->dvb_dmxdev.capabilities = 0;
242
243 if ((ret = dvb_dmx_init(&as102_dev->dvb_dmx)) < 0) {
244 err("%s: dvb_dmx_init() failed (errno = %d)",
245 __FUNCTION__, ret);
246 goto failed;
247 }
248
249 ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
250 if (ret < 0) {
251 err("%s: dvb_dmxdev_init() failed (errno = %d)",
252 __FUNCTION__, ret);
253 goto failed;
254 }
255
256 ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
257 if (ret < 0) {
258 err("%s: as102_dvb_register_frontend() failed (errno = %d)",
259 __FUNCTION__, ret);
260 goto failed;
261 }
262#endif
263
264 /* init bus mutex for token locking */
265 mutex_init(&as102_dev->bus_adap.lock);
266
267 /* init start / stop stream mutex */
268 mutex_init(&as102_dev->sem);
269
270#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
271 /*
272 * try to load as102 firmware. If firmware upload failed, we'll be
273 * able to upload it later.
274 */
275 if (fw_upload)
276 try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
277 "firmware_class");
278#endif
279
280failed:
281 LEAVE();
282 /* FIXME: free dvb_XXX */
283 return ret;
284}
285
286void as102_dvb_unregister(struct as102_dev_t *as102_dev) {
287 ENTER();
288
289#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
290 /* unregister as102 frontend */
291 as102_dvb_unregister_fe(&as102_dev->dvb_fe);
292
293 /* unregister demux device */
294 dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
295 dvb_dmx_release(&as102_dev->dvb_dmx);
296
297 /* unregister dvb adapter */
298 dvb_unregister_adapter(&as102_dev->dvb_adap);
299#endif
300 LEAVE();
301}
302
303static int __init as102_driver_init(void) {
304 int ret = 0;
305
306 ENTER();
307
308 /* register this driver with the low level subsystem */
309#if defined(CONFIG_AS102_USB)
310 ret = usb_register(&as102_usb_driver);
311 if (ret)
312 err("usb_register failed (ret = %d)", ret);
313#endif
314#if defined(CONFIG_AS102_SPI)
315 ret = spi_register_driver(&as102_spi_driver);
316 if (ret)
317 printk(KERN_ERR "spi_register failed (ret = %d)", ret);
318#endif
319
320 LEAVE();
321 return ret;
322}
323
324/*
325 * Mandatory function : Adds a special section to the module indicating
326 * where initialisation function is defined
327 */
328module_init(as102_driver_init);
329
330/**
331 * \brief as102 driver exit point. This function is called when device has
332 * to be removed.
333 */
334static void __exit as102_driver_exit(void) {
335 ENTER();
336 /* deregister this driver with the low level bus subsystem */
337#if defined(CONFIG_AS102_USB)
338 usb_deregister(&as102_usb_driver);
339#endif
340#if defined(CONFIG_AS102_SPI)
341 spi_unregister_driver(&as102_spi_driver);
342#endif
343 LEAVE();
344}
345
346/*
347 * required function for unload: Adds a special section to the module
348 * indicating where unload function is defined
349 */
350module_exit(as102_driver_exit);
351/* modinfo details */
352MODULE_DESCRIPTION(DRIVER_FULL_NAME);
353MODULE_LICENSE("GPL");
354MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
355
356/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h
new file mode 100644
index 00000000000..f50bb9f67fc
--- /dev/null
+++ b/drivers/staging/media/as102/as102_drv.h
@@ -0,0 +1,146 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#if defined(CONFIG_AS102_USB)
21#include <linux/usb.h>
22extern struct usb_driver as102_usb_driver;
23#endif
24
25#if defined(CONFIG_AS102_SPI)
26#include <linux/platform_device.h>
27#include <linux/spi/spi.h>
28#include <linux/cdev.h>
29
30extern struct spi_driver as102_spi_driver;
31#endif
32
33#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
34#include "dvb_demux.h"
35#include "dvb_frontend.h"
36#include "dmxdev.h"
37#endif
38
39#define DRIVER_FULL_NAME "Abilis Systems as10x usb driver"
40#define DRIVER_NAME "as10x_usb"
41
42extern int debug;
43
44#define dprintk(debug, args...) \
45 do { if (debug) { \
46 printk(KERN_DEBUG "%s: ",__FUNCTION__); \
47 printk(args); \
48 } } while (0)
49
50#ifdef TRACE
51#define ENTER() printk(">> enter %s\n", __FUNCTION__)
52#define LEAVE() printk("<< leave %s\n", __FUNCTION__)
53#else
54#define ENTER()
55#define LEAVE()
56#endif
57
58#define AS102_DEVICE_MAJOR 192
59
60#define AS102_USB_BUF_SIZE 512
61#define MAX_STREAM_URB 32
62
63#include "as10x_cmd.h"
64
65#if defined(CONFIG_AS102_USB)
66#include "as102_usb_drv.h"
67#endif
68
69#if defined(CONFIG_AS102_SPI)
70#include "as10x_spi_drv.h"
71#endif
72
73
74struct as102_bus_adapter_t {
75#if defined(CONFIG_AS102_USB)
76 struct usb_device *usb_dev;
77#elif defined(CONFIG_AS102_SPI)
78 struct spi_device *spi_dev;
79 struct cdev cdev; /* spidev raw device */
80
81 struct timer_list timer;
82 struct completion xfer_done;
83#endif
84 /* bus token lock */
85 struct mutex lock;
86 /* low level interface for bus adapter */
87 union as10x_bus_token_t {
88#if defined(CONFIG_AS102_USB)
89 /* usb token */
90 struct as10x_usb_token_cmd_t usb;
91#endif
92#if defined(CONFIG_AS102_SPI)
93 /* spi token */
94 struct as10x_spi_token_cmd_t spi;
95#endif
96 } token;
97
98 /* token cmd xfer id */
99 uint16_t cmd_xid;
100
101 /* as10x command and response for dvb interface*/
102 struct as10x_cmd_t *cmd, *rsp;
103
104 /* bus adapter private ops callback */
105 struct as102_priv_ops_t *ops;
106};
107
108struct as102_dev_t {
109 struct as102_bus_adapter_t bus_adap;
110 struct list_head device_entry;
111 struct kref kref;
112 unsigned long minor;
113
114#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
115 struct dvb_adapter dvb_adap;
116 struct dvb_frontend dvb_fe;
117 struct dvb_demux dvb_dmx;
118 struct dmxdev dvb_dmxdev;
119#endif
120
121 /* demodulator stats */
122 struct as10x_demod_stats demod_stats;
123 /* signal strength */
124 uint16_t signal_strength;
125 /* bit error rate */
126 uint32_t ber;
127
128 /* timer handle to trig ts stream download */
129 struct timer_list timer_handle;
130
131 struct mutex sem;
132 dma_addr_t dma_addr;
133 void *stream;
134 int streaming;
135 struct urb *stream_urb[MAX_STREAM_URB];
136};
137
138int as102_dvb_register(struct as102_dev_t *dev);
139void as102_dvb_unregister(struct as102_dev_t *dev);
140
141#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
142int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe);
143int as102_dvb_unregister_fe(struct dvb_frontend *dev);
144#endif
145
146/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c
new file mode 100644
index 00000000000..3e6f497aed5
--- /dev/null
+++ b/drivers/staging/media/as102/as102_fe.c
@@ -0,0 +1,647 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#include <linux/version.h>
20
21#include "as102_drv.h"
22#include "as10x_types.h"
23#include "as10x_cmd.h"
24
25extern int elna_enable;
26
27#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
28static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
29 struct as10x_tps *src);
30
31static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst,
32 struct dvb_frontend_parameters *src);
33
34static void as102_fe_release(struct dvb_frontend *fe) {
35 struct as102_dev_t *dev;
36
37 ENTER();
38
39 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
40 return;
41
42#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
43 if (mutex_lock_interruptible(&dev->bus_adap.lock))
44 return;
45
46 /* send abilis command: TURN_OFF */
47 as10x_cmd_turn_off(&dev->bus_adap);
48
49 mutex_unlock(&dev->bus_adap.lock);
50#endif
51
52 /* release frontend callback ops */
53 memset(&fe->ops, 0, sizeof(struct dvb_frontend_ops));
54
55 /* flush statistics */
56 memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
57 dev->signal_strength = 0;
58 dev->ber = -1;
59
60 /* reset tuner private data */
61/* fe->tuner_priv = NULL; */
62
63 LEAVE();
64}
65
66#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
67static int as102_fe_init(struct dvb_frontend *fe) {
68 int ret = 0;
69 struct as102_dev_t *dev;
70
71 ENTER();
72
73 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
74 return -ENODEV;
75
76 if (mutex_lock_interruptible(&dev->bus_adap.lock))
77 return -EBUSY;
78
79 if (elna_enable)
80 ret = as10x_cmd_set_context(&dev->bus_adap, 1010, 0xC0);
81
82 /* send abilis command: TURN_ON */
83 ret = as10x_cmd_turn_on(&dev->bus_adap);
84
85 mutex_unlock(&dev->bus_adap.lock);
86
87 LEAVE();
88 return (ret < 0) ? -EINVAL : 0;
89}
90#endif
91
92static int as102_fe_set_frontend(struct dvb_frontend *fe,
93 struct dvb_frontend_parameters *params) {
94 int ret = 0;
95 struct as102_dev_t *dev;
96 struct as10x_tune_args tune_args = { 0 };
97
98 ENTER();
99
100 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
101 return -ENODEV;
102
103 if (mutex_lock_interruptible(&dev->bus_adap.lock))
104 return -EBUSY;
105
106 as102_fe_copy_tune_parameters(&tune_args, params);
107
108 /* send abilis command: SET_TUNE */
109 ret = as10x_cmd_set_tune(&dev->bus_adap, &tune_args);
110 if(ret != 0) {
111 dprintk(debug, "as10x_cmd_set_tune failed. (err = %d)\n", ret);
112 }
113
114 mutex_unlock(&dev->bus_adap.lock);
115
116 LEAVE();
117 return (ret < 0) ? -EINVAL : 0;
118}
119
120static int as102_fe_get_frontend(struct dvb_frontend* fe,
121 struct dvb_frontend_parameters *p) {
122 int ret = 0;
123 struct as102_dev_t *dev;
124 struct as10x_tps tps = { 0 };
125
126 ENTER();
127
128 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
129 return -EINVAL;
130
131 if (mutex_lock_interruptible(&dev->bus_adap.lock))
132 return -EBUSY;
133
134 /* send abilis command: GET_TPS */
135 ret = as10x_cmd_get_tps(&dev->bus_adap, &tps);
136
137 if (ret == 0)
138 as10x_fe_copy_tps_parameters(p, &tps);
139
140 mutex_unlock(&dev->bus_adap.lock);
141
142 LEAVE();
143 return (ret < 0) ? -EINVAL : 0;
144}
145
146static int as102_fe_get_tune_settings(struct dvb_frontend *fe,
147 struct dvb_frontend_tune_settings *settings) {
148 ENTER();
149
150#if 0
151 dprintk(debug, "step_size = %d\n", settings->step_size);
152 dprintk(debug, "max_drift = %d\n", settings->max_drift);
153 dprintk(debug, "min_delay_ms = %d -> %d\n", settings->min_delay_ms, 1000);
154#endif
155
156 settings->min_delay_ms = 1000;
157
158 LEAVE();
159 return 0;
160}
161
162
163static int as102_fe_read_status(struct dvb_frontend *fe, fe_status_t *status) {
164 int ret = 0;
165 struct as102_dev_t *dev;
166 struct as10x_tune_status tstate = { 0 };
167
168 ENTER();
169
170 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
171 return -ENODEV;
172
173 if (mutex_lock_interruptible(&dev->bus_adap.lock))
174 return -EBUSY;
175
176 /* send abilis command: GET_TUNE_STATUS */
177 ret = as10x_cmd_get_tune_status(&dev->bus_adap, &tstate);
178 if (ret < 0) {
179 dprintk(debug, "as10x_cmd_get_tune_status failed (err = %d)\n", ret);
180 goto out;
181 }
182
183 dev->signal_strength = tstate.signal_strength;
184 dev->ber = tstate.BER;
185
186 switch(tstate.tune_state) {
187 case TUNE_STATUS_SIGNAL_DVB_OK:
188 *status = FE_HAS_SIGNAL |
189 FE_HAS_CARRIER;
190 break;
191 case TUNE_STATUS_STREAM_DETECTED:
192 *status = FE_HAS_SIGNAL |
193 FE_HAS_CARRIER |
194 FE_HAS_SYNC;
195 break;
196 case TUNE_STATUS_STREAM_TUNED:
197 *status = FE_HAS_SIGNAL |
198 FE_HAS_CARRIER |
199 FE_HAS_SYNC |
200 FE_HAS_LOCK;
201 break;
202 default:
203 *status = TUNE_STATUS_NOT_TUNED;
204 }
205
206 dprintk(debug, "tuner status: 0x%02x , strength %d , per: %d , ber: %d\n",
207 tstate.tune_state, tstate.signal_strength,
208 tstate.PER, tstate.BER);
209
210 if (*status & FE_HAS_LOCK) {
211 if (as10x_cmd_get_demod_stats(&dev->bus_adap,
212 (struct as10x_demod_stats *) &dev->demod_stats) < 0) {
213 memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
214 dprintk(debug, "as10x_cmd_get_demod_stats failed (probably not tuned)\n");
215 } else {
216 dprintk(debug, "demod status: fc: 0x%08x , bad fc: 0x%08x , bytes corrected: 0x%08x , MER: 0x%04x\n",
217 dev->demod_stats.frame_count,
218 dev->demod_stats.bad_frame_count,
219 dev->demod_stats.bytes_fixed_by_rs,
220 dev->demod_stats.mer);
221 }
222 } else {
223 memset(&dev->demod_stats, 0, sizeof(dev->demod_stats));
224 }
225
226out:
227 mutex_unlock(&dev->bus_adap.lock);
228 LEAVE();
229 return ret;
230}
231
232/*
233 * Note:
234 * - in AS102 SNR=MER
235 * - the SNR will be returned in linear terms, i.e. not in dB
236 * - the accuracy equals ±2dB for a SNR range from 4dB to 30dB
237 * - the accuracy is >2dB for SNR values outside this range
238 */
239static int as102_fe_read_snr(struct dvb_frontend* fe, u16* snr) {
240 struct as102_dev_t *dev;
241
242 ENTER();
243
244 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
245 return -ENODEV;
246
247 *snr = dev->demod_stats.mer;
248
249 LEAVE();
250 return 0;
251}
252
253static int as102_fe_read_ber(struct dvb_frontend* fe, u32* ber) {
254 struct as102_dev_t *dev;
255
256 ENTER();
257
258 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
259 return -ENODEV;
260
261 *ber = dev->ber;
262
263 LEAVE();
264 return 0;
265}
266
267static int as102_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength) {
268 struct as102_dev_t *dev;
269
270 ENTER();
271
272 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
273 return -ENODEV;
274
275 *strength = (((0xffff * 400) * dev->signal_strength + 41000) * 2);
276
277 LEAVE();
278 return 0;
279}
280
281static int as102_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) {
282 struct as102_dev_t *dev;
283
284 ENTER();
285
286 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
287 return -ENODEV;
288
289 if (dev->demod_stats.has_started)
290 *ucblocks = dev->demod_stats.bad_frame_count;
291 else
292 *ucblocks = 0;
293
294 LEAVE();
295 return 0;
296}
297
298#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
299static int as102_fe_ts_bus_ctrl(struct dvb_frontend* fe, int acquire) {
300 struct as102_dev_t *dev;
301 int ret;
302
303 ENTER();
304
305 if ((dev = (struct as102_dev_t *) fe->tuner_priv) == NULL)
306 return -ENODEV;
307
308 if (mutex_lock_interruptible(&dev->bus_adap.lock))
309 return -EBUSY;
310
311 if (acquire) {
312 if (elna_enable)
313 as10x_cmd_set_context(&dev->bus_adap, 1010, 0xC0);
314
315 ret = as10x_cmd_turn_on(&dev->bus_adap);
316 } else {
317 ret = as10x_cmd_turn_off(&dev->bus_adap);
318 }
319
320 mutex_unlock(&dev->bus_adap.lock);
321
322 LEAVE();
323 return ret;
324}
325#endif
326
327static struct dvb_frontend_ops as102_fe_ops = {
328 .info = {
329 .name = DEVICE_FULL_NAME,
330 .type = FE_OFDM,
331 .frequency_min = 174000000,
332 .frequency_max = 862000000,
333 .frequency_stepsize = 166667,
334 .caps = FE_CAN_INVERSION_AUTO
335 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
336 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO
337 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK
338 | FE_CAN_QAM_AUTO
339 | FE_CAN_TRANSMISSION_MODE_AUTO
340 | FE_CAN_GUARD_INTERVAL_AUTO
341 | FE_CAN_HIERARCHY_AUTO
342 | FE_CAN_RECOVER
343 | FE_CAN_MUTE_TS
344 },
345
346 .set_frontend = as102_fe_set_frontend,
347 .get_frontend = as102_fe_get_frontend,
348 .get_tune_settings = as102_fe_get_tune_settings,
349
350
351 .read_status = as102_fe_read_status,
352 .read_snr = as102_fe_read_snr,
353 .read_ber = as102_fe_read_ber,
354 .read_signal_strength = as102_fe_read_signal_strength,
355 .read_ucblocks = as102_fe_read_ucblocks,
356
357#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
358 .ts_bus_ctrl = as102_fe_ts_bus_ctrl,
359#else
360 .release = as102_fe_release,
361 .init = as102_fe_init,
362#endif
363};
364
365int as102_dvb_unregister_fe(struct dvb_frontend *fe) {
366
367 /* unregister frontend */
368 dvb_unregister_frontend(fe);
369
370#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
371 /* detach frontend */
372 dvb_frontend_detach(fe);
373#endif
374 return 0;
375}
376
377int as102_dvb_register_fe(struct as102_dev_t *as102_dev, struct dvb_frontend *dvb_fe) {
378 int errno;
379 struct dvb_adapter *dvb_adap;
380
381 if(as102_dev == NULL)
382 return -EINVAL;
383
384 /* extract dvb_adapter */
385 dvb_adap = &as102_dev->dvb_adap;
386
387 /* init frontend callback ops */
388 memcpy(&dvb_fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops));
389
390 /* register dbvb frontend */
391 errno = dvb_register_frontend(dvb_adap, dvb_fe);
392 if(errno == 0)
393 dvb_fe->tuner_priv = as102_dev;
394
395 return errno;
396}
397
398static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
399 struct as10x_tps *as10x_tps) {
400
401 struct dvb_ofdm_parameters *fe_tps = &dst->u.ofdm;
402
403 /* extract consteallation */
404 switch(as10x_tps->constellation) {
405 case CONST_QPSK:
406 fe_tps->constellation = QPSK;
407 break;
408 case CONST_QAM16:
409 fe_tps->constellation = QAM_16;
410 break;
411 case CONST_QAM64:
412 fe_tps->constellation = QAM_64;
413 break;
414 }
415
416 /* extract hierarchy */
417 switch(as10x_tps->hierarchy) {
418 case HIER_NONE:
419 fe_tps->hierarchy_information = HIERARCHY_NONE;
420 break;
421 case HIER_ALPHA_1:
422 fe_tps->hierarchy_information = HIERARCHY_1;
423 break;
424 case HIER_ALPHA_2:
425 fe_tps->hierarchy_information = HIERARCHY_2;
426 break;
427 case HIER_ALPHA_4:
428 fe_tps->hierarchy_information = HIERARCHY_4;
429 break;
430 }
431
432 /* extract code rate HP */
433 switch(as10x_tps->code_rate_HP) {
434 case CODE_RATE_1_2:
435 fe_tps->code_rate_HP = FEC_1_2;
436 break;
437 case CODE_RATE_2_3:
438 fe_tps->code_rate_HP = FEC_2_3;
439 break;
440 case CODE_RATE_3_4:
441 fe_tps->code_rate_HP = FEC_3_4;
442 break;
443 case CODE_RATE_5_6:
444 fe_tps->code_rate_HP = FEC_5_6;
445 break;
446 case CODE_RATE_7_8:
447 fe_tps->code_rate_HP = FEC_7_8;
448 break;
449 }
450
451 /* extract code rate LP */
452 switch(as10x_tps->code_rate_LP) {
453 case CODE_RATE_1_2:
454 fe_tps->code_rate_LP = FEC_1_2;
455 break;
456 case CODE_RATE_2_3:
457 fe_tps->code_rate_LP = FEC_2_3;
458 break;
459 case CODE_RATE_3_4:
460 fe_tps->code_rate_LP = FEC_3_4;
461 break;
462 case CODE_RATE_5_6:
463 fe_tps->code_rate_LP = FEC_5_6;
464 break;
465 case CODE_RATE_7_8:
466 fe_tps->code_rate_LP = FEC_7_8;
467 break;
468 }
469
470 /* extract guard interval */
471 switch(as10x_tps->guard_interval) {
472 case GUARD_INT_1_32:
473 fe_tps->guard_interval = GUARD_INTERVAL_1_32;
474 break;
475 case GUARD_INT_1_16:
476 fe_tps->guard_interval = GUARD_INTERVAL_1_16;
477 break;
478 case GUARD_INT_1_8:
479 fe_tps->guard_interval = GUARD_INTERVAL_1_8;
480 break;
481 case GUARD_INT_1_4:
482 fe_tps->guard_interval = GUARD_INTERVAL_1_4;
483 break;
484 }
485
486 /* extract transmission mode */
487 switch(as10x_tps->transmission_mode) {
488 case TRANS_MODE_2K:
489 fe_tps->transmission_mode = TRANSMISSION_MODE_2K;
490 break;
491 case TRANS_MODE_8K:
492 fe_tps->transmission_mode = TRANSMISSION_MODE_8K;
493 break;
494 }
495}
496
497static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg) {
498 uint8_t c;
499
500 switch(arg) {
501 case FEC_1_2:
502 c = CODE_RATE_1_2;
503 break;
504 case FEC_2_3:
505 c = CODE_RATE_2_3;
506 break;
507 case FEC_3_4:
508 c = CODE_RATE_3_4;
509 break;
510 case FEC_5_6:
511 c = CODE_RATE_5_6;
512 break;
513 case FEC_7_8:
514 c = CODE_RATE_7_8;
515 break;
516 default:
517 c = CODE_RATE_UNKNOWN;
518 break;
519 }
520
521 return c;
522}
523
524static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
525 struct dvb_frontend_parameters *params) {
526
527 /* set frequency */
528 tune_args->freq = params->frequency / 1000;
529
530 /* fix interleaving_mode */
531 tune_args->interleaving_mode = INTLV_NATIVE;
532
533 switch(params->u.ofdm.bandwidth) {
534 case BANDWIDTH_8_MHZ:
535 tune_args->bandwidth = BW_8_MHZ;
536 break;
537 case BANDWIDTH_7_MHZ:
538 tune_args->bandwidth = BW_7_MHZ;
539 break;
540 case BANDWIDTH_6_MHZ:
541 tune_args->bandwidth = BW_6_MHZ;
542 break;
543 default:
544 tune_args->bandwidth = BW_8_MHZ;
545 }
546
547 switch(params->u.ofdm.guard_interval) {
548 case GUARD_INTERVAL_1_32:
549 tune_args->guard_interval = GUARD_INT_1_32;
550 break;
551 case GUARD_INTERVAL_1_16:
552 tune_args->guard_interval = GUARD_INT_1_16;
553 break;
554 case GUARD_INTERVAL_1_8:
555 tune_args->guard_interval = GUARD_INT_1_8;
556 break;
557 case GUARD_INTERVAL_1_4:
558 tune_args->guard_interval = GUARD_INT_1_4;
559 break;
560 case GUARD_INTERVAL_AUTO:
561 default:
562 tune_args->guard_interval = GUARD_UNKNOWN;
563 break;
564 }
565
566 switch(params->u.ofdm.constellation) {
567 case QPSK:
568 tune_args->constellation = CONST_QPSK;
569 break;
570 case QAM_16:
571 tune_args->constellation = CONST_QAM16;
572 break;
573 case QAM_64:
574 tune_args->constellation = CONST_QAM64;
575 break;
576 default:
577 tune_args->constellation = CONST_UNKNOWN;
578 break;
579 }
580
581 switch(params->u.ofdm.transmission_mode) {
582 case TRANSMISSION_MODE_2K:
583 tune_args->transmission_mode = TRANS_MODE_2K;
584 break;
585 case TRANSMISSION_MODE_8K:
586 tune_args->transmission_mode = TRANS_MODE_8K;
587 break;
588 default:
589 tune_args->transmission_mode = TRANS_MODE_UNKNOWN;
590 }
591
592 switch(params->u.ofdm.hierarchy_information) {
593 case HIERARCHY_NONE:
594 tune_args->hierarchy = HIER_NONE;
595 break;
596 case HIERARCHY_1:
597 tune_args->hierarchy = HIER_ALPHA_1;
598 break;
599 case HIERARCHY_2:
600 tune_args->hierarchy = HIER_ALPHA_2;
601 break;
602 case HIERARCHY_4:
603 tune_args->hierarchy = HIER_ALPHA_4;
604 break;
605 case HIERARCHY_AUTO:
606 tune_args->hierarchy = HIER_UNKNOWN;
607 break;
608 }
609
610 dprintk(debug, "tuner parameters: freq: %d bw: 0x%02x gi: 0x%02x\n",
611 params->frequency,
612 tune_args->bandwidth,
613 tune_args->guard_interval);
614
615 /*
616 * Detect a hierarchy selection
617 * if HP/LP are both set to FEC_NONE, HP will be selected.
618 */
619 if ((tune_args->hierarchy != HIER_NONE) &&
620 ((params->u.ofdm.code_rate_LP == FEC_NONE) ||
621 (params->u.ofdm.code_rate_HP == FEC_NONE))) {
622
623 if (params->u.ofdm.code_rate_LP == FEC_NONE) {
624 tune_args->hier_select = HIER_HIGH_PRIORITY;
625 tune_args->code_rate =
626 as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
627 }
628
629 if (params->u.ofdm.code_rate_HP == FEC_NONE) {
630 tune_args->hier_select = HIER_LOW_PRIORITY;
631 tune_args->code_rate =
632 as102_fe_get_code_rate(params->u.ofdm.code_rate_LP);
633 }
634
635 dprintk(debug, "\thierarchy: 0x%02x "
636 "selected: %s code_rate_%s: 0x%02x\n",
637 tune_args->hierarchy,
638 tune_args->hier_select == HIER_HIGH_PRIORITY ? "HP" : "LP",
639 tune_args->hier_select == HIER_HIGH_PRIORITY ? "HP" : "LP",
640 tune_args->code_rate);
641 } else {
642 tune_args->code_rate = as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
643 }
644}
645#endif
646
647/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c
new file mode 100644
index 00000000000..d921a6fd695
--- /dev/null
+++ b/drivers/staging/media/as102/as102_fw.c
@@ -0,0 +1,236 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/ctype.h>
22#include <linux/delay.h>
23#include <linux/firmware.h>
24
25#include "as102_drv.h"
26#include "as102_fw.h"
27
28#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
29char as102_st_fw1[] = "as102_data1_st.hex";
30char as102_st_fw2[] = "as102_data2_st.hex";
31char as102_dt_fw1[] = "as102_data1_dt.hex";
32char as102_dt_fw2[] = "as102_data2_dt.hex";
33
34static unsigned char atohx(unsigned char *dst, char *src) {
35 unsigned char value = 0;
36
37 char msb = tolower(*src) - '0';
38 char lsb = tolower(*(src +1)) - '0';
39
40 if (msb > 9 )
41 msb -= 7;
42 if (lsb > 9 )
43 lsb -= 7;
44
45 *dst = value = ((msb & 0xF) << 4) | (lsb & 0xF);
46 return value;
47}
48
49/*
50 * Parse INTEL HEX firmware file to extract address and data.
51 */
52static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
53 unsigned char *data, int *dataLength,
54 unsigned char *addr_has_changed) {
55
56 int count = 0;
57 unsigned char *src, dst;
58
59 if (*fw_data++ != ':') {
60 printk(KERN_ERR "invalid firmware file\n");
61 return -EFAULT;
62 }
63
64 /* locate end of line */
65 for (src=fw_data; *src != '\n'; src += 2) {
66 atohx(&dst, src);
67 /* parse line to split addr / data */
68 switch (count) {
69 case 0:
70 *dataLength = dst;
71 break;
72 case 1:
73 addr[2] = dst;
74 break;
75 case 2:
76 addr[3] = dst;
77 break;
78 case 3:
79 /* check if data is an address */
80 if (dst == 0x04)
81 *addr_has_changed = 1;
82 else
83 *addr_has_changed = 0;
84 break;
85 case 4:
86 case 5:
87 if (*addr_has_changed) {
88 addr[(count - 4)] = dst;
89 } else {
90 data[(count - 4)] = dst;
91 }
92 break;
93 default:
94 data[(count - 4)] = dst;
95 break;
96 }
97 count++;
98 }
99
100 /* return read value + ':' + '\n' */
101 return ((count * 2) + 2);
102}
103
104static int as102_firmware_upload(struct as102_bus_adapter_t *bus_adap,
105 unsigned char *cmd,
106 const struct firmware *firmware) {
107
108 struct as10x_fw_pkt_t fw_pkt;
109 int total_read_bytes = 0, errno = 0;
110 unsigned char addr_has_changed = 0;
111
112 ENTER();
113
114 for (total_read_bytes = 0; total_read_bytes < firmware->size; ) {
115 int read_bytes = 0, data_len = 0;
116
117 /* parse intel hex line */
118 read_bytes = parse_hex_line(
119 (u8 *) (firmware->data + total_read_bytes),
120 fw_pkt.raw.address,
121 fw_pkt.raw.data,
122 &data_len,
123 &addr_has_changed);
124
125 if (read_bytes <= 0) {
126 goto error;
127 }
128
129 /* detect the end of file */
130 if ((total_read_bytes += read_bytes) == firmware->size) {
131 fw_pkt.u.request[0] = 0x00;
132 fw_pkt.u.request[1] = 0x03;
133
134 /* send EOF command */
135 if ((errno = bus_adap->ops->upload_fw_pkt(bus_adap,(uint8_t *) &fw_pkt, 2, 0)) < 0)
136 goto error;
137 } else {
138 if (!addr_has_changed) {
139 /* prepare command to send */
140 fw_pkt.u.request[0] = 0x00;
141 fw_pkt.u.request[1] = 0x01;
142
143 data_len += sizeof(fw_pkt.u.request);
144 data_len += sizeof(fw_pkt.raw.address);
145
146 /* send cmd to device */
147 if ((errno = bus_adap->ops->upload_fw_pkt(bus_adap, (uint8_t *) &fw_pkt, data_len, 0)) < 0)
148 goto error;
149 }
150 }
151 }
152error:
153 LEAVE();
154 return (errno == 0) ? total_read_bytes : errno;
155}
156
157int as102_fw_upload(struct as102_bus_adapter_t *bus_adap) {
158 int errno = -EFAULT;
159 const struct firmware *firmware;
160 unsigned char *cmd_buf = NULL;
161 char *fw1, *fw2;
162
163#if defined(CONFIG_AS102_USB)
164 struct usb_device *dev = bus_adap->usb_dev;
165#endif
166#if defined(CONFIG_AS102_SPI)
167 struct spi_device *dev = bus_adap->spi_dev;
168#endif
169 ENTER();
170
171 /* select fw file to upload */
172 if (dual_tuner) {
173 fw1 = as102_dt_fw1;
174 fw2 = as102_dt_fw2;
175 } else {
176 fw1 = as102_st_fw1;
177 fw2 = as102_st_fw2;
178 }
179
180#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
181 /* allocate buffer to store firmware upload command and data */
182 if ((cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL)) == NULL) {
183 errno = -ENOMEM;
184 goto error;
185 }
186
187 /* request kernel to locate firmware file: part1 */
188 if ((errno = request_firmware(&firmware, fw1, &dev->dev)) < 0) {
189 printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
190 DRIVER_NAME, fw1);
191 goto error;
192 }
193
194 /* initiate firmware upload */
195 if ((errno = as102_firmware_upload(bus_adap, cmd_buf, firmware)) < 0) {
196 printk(KERN_ERR "%s: error during firmware upload part1\n",
197 DRIVER_NAME);
198 goto error;
199 }
200
201 printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
202 DRIVER_NAME, fw1);
203 release_firmware(firmware);
204
205 /* wait for boot to complete */
206 mdelay(100);
207
208 /* request kernel to locate firmware file: part2 */
209 if ((errno = request_firmware(&firmware, fw2, &dev->dev)) < 0) {
210 printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
211 DRIVER_NAME, fw2);
212 goto error;
213 }
214
215 /* initiate firmware upload */
216 if ((errno = as102_firmware_upload(bus_adap, cmd_buf, firmware)) < 0) {
217 printk(KERN_ERR "%s: error during firmware upload part2\n",
218 DRIVER_NAME);
219 goto error;
220 }
221
222 printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
223 DRIVER_NAME, fw2);
224error:
225 /* free data buffer */
226 kfree(cmd_buf);
227 /* release firmware if needed */
228 if (firmware != NULL)
229 release_firmware(firmware);
230#endif
231 LEAVE();
232 return errno;
233}
234#endif
235
236/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h
new file mode 100644
index 00000000000..27e5347e2e1
--- /dev/null
+++ b/drivers/staging/media/as102/as102_fw.h
@@ -0,0 +1,42 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#define MAX_FW_PKT_SIZE 64
20
21extern int dual_tuner;
22
23#pragma pack(1)
24struct as10x_raw_fw_pkt {
25 unsigned char address[4];
26 unsigned char data[MAX_FW_PKT_SIZE - 6];
27};
28
29struct as10x_fw_pkt_t {
30 union {
31 unsigned char request[2];
32 unsigned char length[2];
33 } u;
34 struct as10x_raw_fw_pkt raw;
35};
36#pragma pack()
37
38#ifdef __KERNEL__
39int as102_fw_upload(struct as102_bus_adapter_t *bus_adap);
40#endif
41
42/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c
new file mode 100644
index 00000000000..ee993960731
--- /dev/null
+++ b/drivers/staging/media/as102/as102_usb_drv.c
@@ -0,0 +1,432 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/slab.h>
22#include <linux/mm.h>
23#include <linux/usb.h>
24
25#include "as102_drv.h"
26#include "as102_usb_drv.h"
27#include "as102_fw.h"
28
29static void as102_usb_disconnect(struct usb_interface *interface);
30static int as102_usb_probe(struct usb_interface *interface,
31 const struct usb_device_id *id);
32
33static int as102_usb_start_stream(struct as102_dev_t *dev);
34static void as102_usb_stop_stream(struct as102_dev_t *dev);
35
36static int as102_open(struct inode *inode, struct file *file);
37static int as102_release(struct inode *inode, struct file *file);
38
39static struct usb_device_id as102_usb_id_table[] = {
40 { USB_DEVICE(AS102_USB_DEVICE_VENDOR_ID, AS102_USB_DEVICE_PID_0001) },
41 { USB_DEVICE(PCTV_74E_USB_VID, PCTV_74E_USB_PID) },
42 { } /* Terminating entry */
43};
44
45struct usb_driver as102_usb_driver = {
46 .name = DRIVER_FULL_NAME,
47 .probe = as102_usb_probe,
48 .disconnect = as102_usb_disconnect,
49 .id_table = as102_usb_id_table
50};
51
52struct file_operations as102_dev_fops = {
53 .owner = THIS_MODULE,
54 .open = as102_open,
55 .release = as102_release,
56};
57
58static struct usb_class_driver as102_usb_class_driver = {
59 .name = "aton2-%d",
60 .fops = &as102_dev_fops,
61 .minor_base = AS102_DEVICE_MAJOR,
62};
63
64static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap,
65 unsigned char *send_buf, int send_buf_len,
66 unsigned char *recv_buf, int recv_buf_len) {
67
68 int ret = 0;
69 ENTER();
70
71 if(send_buf != NULL) {
72 ret = usb_control_msg(bus_adap->usb_dev,
73 usb_sndctrlpipe(bus_adap->usb_dev, 0),
74 AS102_USB_DEVICE_TX_CTRL_CMD,
75 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
76 bus_adap->cmd_xid, /* value */
77 0, /* index */
78 send_buf, send_buf_len,
79 USB_CTRL_SET_TIMEOUT /* 200 */);
80 if(ret < 0) {
81 dprintk(debug, "usb_control_msg(send) failed, err %i\n",
82 ret);
83 return ret;
84 }
85
86 if(ret != send_buf_len) {
87 dprintk(debug, "only wrote %d of %d bytes\n",
88 ret, send_buf_len);
89 return -1;
90 }
91 }
92
93 if(recv_buf != NULL) {
94#ifdef TRACE
95 dprintk(debug, "want to read: %d bytes\n", recv_buf_len);
96#endif
97 ret = usb_control_msg(bus_adap->usb_dev,
98 usb_rcvctrlpipe(bus_adap->usb_dev, 0),
99 AS102_USB_DEVICE_RX_CTRL_CMD,
100 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
101 bus_adap->cmd_xid, /* value */
102 0, /* index */
103 recv_buf, recv_buf_len,
104 USB_CTRL_GET_TIMEOUT /* 200 */);
105 if(ret < 0) {
106 dprintk(debug, "usb_control_msg(recv) failed, err %i\n",
107 ret);
108 return ret;
109 }
110#ifdef TRACE
111 dprintk(debug, "read %d bytes\n", recv_buf_len);
112#endif
113 }
114
115 LEAVE();
116 return ret;
117}
118
119static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap,
120 unsigned char *send_buf,
121 int send_buf_len,
122 int swap32) {
123
124 int ret = 0, actual_len;
125
126 ret = usb_bulk_msg(bus_adap->usb_dev, usb_sndbulkpipe(bus_adap->usb_dev, 1),
127 send_buf, send_buf_len, &actual_len, 200);
128 if(ret) {
129 dprintk(debug, "usb_bulk_msg(send) failed, err %i\n", ret);
130 return ret;
131 }
132
133 if(actual_len != send_buf_len) {
134 dprintk(debug, "only wrote %d of %d bytes\n",
135 actual_len, send_buf_len);
136 return -1;
137 }
138 return ret ? ret : actual_len;
139}
140
141static int as102_read_ep2(struct as102_bus_adapter_t *bus_adap,
142 unsigned char *recv_buf, int recv_buf_len) {
143
144 int ret = 0, actual_len;
145
146 if(recv_buf == NULL)
147 return -EINVAL;
148
149 ret = usb_bulk_msg(bus_adap->usb_dev, usb_rcvbulkpipe(bus_adap->usb_dev, 2),
150 recv_buf, recv_buf_len, &actual_len, 200);
151 if(ret) {
152 dprintk(debug, "usb_bulk_msg(recv) failed, err %i\n", ret);
153 return ret;
154 }
155
156 if(actual_len != recv_buf_len) {
157 dprintk(debug, "only read %d of %d bytes\n",
158 actual_len, recv_buf_len);
159 return -1;
160 }
161 return ret ? ret : actual_len;
162}
163
164struct as102_priv_ops_t as102_priv_ops = {
165 .upload_fw_pkt = as102_send_ep1,
166 .xfer_cmd = as102_usb_xfer_cmd,
167 .as102_read_ep2 = as102_read_ep2,
168 .start_stream = as102_usb_start_stream,
169 .stop_stream = as102_usb_stop_stream,
170};
171
172static int as102_submit_urb_stream(struct as102_dev_t *dev, struct urb *urb) {
173 int err;
174
175 usb_fill_bulk_urb(urb,
176 dev->bus_adap.usb_dev,
177 usb_rcvbulkpipe(dev->bus_adap.usb_dev, 0x2),
178 urb->transfer_buffer,
179 AS102_USB_BUF_SIZE,
180 as102_urb_stream_irq,
181 dev);
182
183 if ((err = usb_submit_urb(urb, GFP_ATOMIC)))
184 dprintk(debug, "%s: usb_submit_urb failed\n", __FUNCTION__);
185
186 return err;
187}
188
189#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18))
190void as102_urb_stream_irq(struct urb *urb, struct pt_regs *regs)
191#else
192void as102_urb_stream_irq(struct urb *urb)
193#endif
194{
195 struct as102_dev_t *as102_dev = urb->context;
196
197 if (urb->actual_length > 0) {
198#if defined(CONFIG_DVB_CORE) || defined(CONFIG_DVB_CORE_MODULE)
199 dvb_dmx_swfilter(&as102_dev->dvb_dmx,
200 urb->transfer_buffer,
201 urb->actual_length);
202#else
203 /* do nothing ? */
204#endif
205 } else {
206 if(urb->actual_length == 0)
207 memset(urb->transfer_buffer, 0, AS102_USB_BUF_SIZE);
208 }
209
210 /* is not stopped, re-submit urb */
211 if (as102_dev->streaming)
212 as102_submit_urb_stream(as102_dev, urb);
213}
214
215static void as102_free_usb_stream_buffer(struct as102_dev_t *dev) {
216 int i;
217
218 ENTER();
219
220 for (i = 0; i < MAX_STREAM_URB; i++)
221 usb_free_urb(dev->stream_urb[i]);
222
223 usb_buffer_free(dev->bus_adap.usb_dev,
224 MAX_STREAM_URB * AS102_USB_BUF_SIZE,
225 dev->stream,
226 dev->dma_addr);
227 LEAVE();
228}
229
230static int as102_alloc_usb_stream_buffer(struct as102_dev_t *dev) {
231 int i, ret = 0;
232
233 ENTER();
234
235 dev->stream = usb_buffer_alloc(dev->bus_adap.usb_dev,
236 MAX_STREAM_URB * AS102_USB_BUF_SIZE,
237 GFP_KERNEL,
238 &dev->dma_addr);
239 if (!dev->stream) {
240 dprintk(debug, "%s: usb_buffer_alloc failed\n", __FUNCTION__);
241 return -ENOMEM;
242 }
243
244 memset(dev->stream, 0, MAX_STREAM_URB * AS102_USB_BUF_SIZE);
245
246 /* init urb buffers */
247 for (i = 0; i < MAX_STREAM_URB; i++) {
248 struct urb *urb;
249
250 if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) {
251 dprintk(debug, "%s: usb_alloc_urb failed\n", __FUNCTION__);
252 as102_free_usb_stream_buffer(dev);
253 return -ENOMEM;
254 }
255
256 urb->transfer_buffer = dev->stream + (i * AS102_USB_BUF_SIZE);
257 urb->transfer_buffer_length = AS102_USB_BUF_SIZE;
258
259 dev->stream_urb[i] = urb;
260 }
261 LEAVE();
262 return ret;
263}
264
265static void as102_usb_stop_stream(struct as102_dev_t *dev) {
266 int i;
267
268 for (i = 0; i < MAX_STREAM_URB; i++)
269 usb_kill_urb(dev->stream_urb[i]);
270}
271
272static int as102_usb_start_stream(struct as102_dev_t *dev) {
273 int i, ret = 0;
274
275 for (i = 0; i < MAX_STREAM_URB; i++) {
276 if ((ret = as102_submit_urb_stream(dev, dev->stream_urb[i]))) {
277 as102_usb_stop_stream(dev);
278 return ret;
279 }
280 }
281
282 return 0;
283}
284
285static void as102_usb_release(struct kref *kref) {
286 struct as102_dev_t *as102_dev;
287
288 ENTER();
289
290 as102_dev = container_of(kref, struct as102_dev_t, kref);
291 if (as102_dev != NULL) {
292 usb_put_dev(as102_dev->bus_adap.usb_dev);
293 kfree(as102_dev);
294 }
295
296 LEAVE();
297}
298
299static void as102_usb_disconnect(struct usb_interface *intf) {
300 struct as102_dev_t *as102_dev;
301
302 ENTER();
303
304 /* extract as102_dev_t from usb_device private data */
305 as102_dev = usb_get_intfdata(intf);
306
307 /* unregister dvb layer */
308 as102_dvb_unregister(as102_dev);
309
310 /* free usb buffers */
311 as102_free_usb_stream_buffer(as102_dev);
312
313 usb_set_intfdata(intf, NULL);
314
315 /* usb unregister device */
316 usb_deregister_dev(intf, &as102_usb_class_driver);
317
318 /* decrement usage counter */
319 kref_put(&as102_dev->kref, as102_usb_release);
320
321 printk(KERN_INFO "%s: device has been disconnected\n", DRIVER_NAME);
322
323 LEAVE();
324}
325
326static int as102_usb_probe(struct usb_interface *intf,
327 const struct usb_device_id *id) {
328 int ret;
329 struct as102_dev_t *as102_dev;
330
331 ENTER();
332
333 if(!(as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL))) {
334 err("%s: kzalloc failed", __FUNCTION__);
335 return -ENOMEM;
336 }
337
338 /* set private callback functions */
339 as102_dev->bus_adap.ops = &as102_priv_ops;
340
341 /* init cmd token for usb bus */
342 as102_dev->bus_adap.cmd = &as102_dev->bus_adap.token.usb.c;
343 as102_dev->bus_adap.rsp = &as102_dev->bus_adap.token.usb.r;
344
345 /* init kernel device reference */
346 kref_init(&as102_dev->kref);
347
348 /* store as102 device to usb_device private data */
349 usb_set_intfdata(intf, (void *) as102_dev);
350
351 /* store in as102 device the usb_device pointer */
352 as102_dev->bus_adap.usb_dev = usb_get_dev(interface_to_usbdev(intf));
353
354 /* we can register the device now, as it is ready */
355 if((ret = usb_register_dev(intf, &as102_usb_class_driver)) < 0) {;
356 /* something prevented us from registering this driver */
357 err("%s: usb_register_dev() failed (errno = %d)",
358 __FUNCTION__, ret);
359 goto failed;
360 }
361
362 printk(KERN_INFO "%s: device has been detected\n", DRIVER_NAME);
363
364 /* request buffer allocation for streaming */
365 if ((ret = as102_alloc_usb_stream_buffer(as102_dev)) != 0)
366 goto failed;
367
368 /* register dvb layer */
369 ret = as102_dvb_register(as102_dev);
370
371 LEAVE();
372 return ret;
373
374failed:
375 usb_set_intfdata(intf, NULL);
376 kfree(as102_dev);
377 return ret;
378}
379
380static int as102_open(struct inode *inode, struct file *file) {
381 int ret = 0, minor = 0;
382 struct usb_interface *intf = NULL;
383 struct as102_dev_t *dev = NULL;
384
385 ENTER();
386
387 /* read minor from inode */
388 minor = iminor(inode);
389
390 /* fetch device from usb interface */
391 if((intf = usb_find_interface(&as102_usb_driver, minor)) == NULL) {
392 printk(KERN_ERR "%s: can't find device for minor %d\n",
393 __FUNCTION__, minor);
394 ret = -ENODEV;
395 goto exit;
396 }
397
398 /* get our device */
399 if((dev = usb_get_intfdata(intf)) == NULL) {
400 ret = -EFAULT;
401 goto exit;
402 }
403
404 /* save our device object in the file's private structure */
405 file->private_data = dev;
406
407 /* increment our usage count for the device */
408 kref_get(&dev->kref);
409
410exit:
411 LEAVE();
412 return ret;
413}
414
415static int as102_release(struct inode *inode, struct file *file) {
416 int ret = 0;
417 struct as102_dev_t *dev = NULL;
418
419 ENTER();
420
421 if((dev = file->private_data) != NULL ) {
422 /* decrement the count on our device */
423 kref_put(&dev->kref, as102_usb_release);
424 }
425
426 LEAVE();
427 return ret;
428}
429
430MODULE_DEVICE_TABLE(usb, as102_usb_id_table);
431
432/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_usb_drv.h b/drivers/staging/media/as102/as102_usb_drv.h
new file mode 100644
index 00000000000..abb858ececb
--- /dev/null
+++ b/drivers/staging/media/as102/as102_usb_drv.h
@@ -0,0 +1,54 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#include <linux/version.h>
20
21#ifndef _AS102_USB_DRV_H_
22#define _AS102_USB_DRV_H_
23
24#define AS102_USB_DEVICE_TX_CTRL_CMD 0xF1
25#define AS102_USB_DEVICE_RX_CTRL_CMD 0xF2
26
27/* define these values to match the supported devices */
28
29/* Abilis system: "TITAN" */
30#define AS102_USB_DEVICE_VENDOR_ID 0x1BA6
31#define AS102_USB_DEVICE_PID_0001 0x0001
32
33/* PCTV Systems: PCTV picoStick (74e) */
34#define DEVICE_FULL_NAME "PCTV Systems : PCTV picoStick (74e)"
35#define PCTV_74E_USB_VID 0x2013
36#define PCTV_74E_USB_PID 0x0246
37
38extern struct file_operations as102_dev_fops;
39
40#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18))
41void as102_urb_stream_irq(struct urb *urb, struct pt_regs *regs);
42#else
43void as102_urb_stream_irq(struct urb *urb);
44#endif
45
46
47struct as10x_usb_token_cmd_t {
48 /* token cmd */
49 struct as10x_cmd_t c;
50 /* token response */
51 struct as10x_cmd_t r;
52};
53#endif
54/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as10x_cmd.c b/drivers/staging/media/as102/as10x_cmd.c
new file mode 100644
index 00000000000..cecb809a51a
--- /dev/null
+++ b/drivers/staging/media/as102/as10x_cmd.c
@@ -0,0 +1,478 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#if defined(LINUX) && defined(__KERNEL__) /* linux kernel implementation */
21#include <linux/kernel.h>
22#include "as102_drv.h"
23#elif defined(WIN32)
24 #if defined(__BUILDMACHINE__) && (__BUILDMACHINE__ == WinDDK) /* win32 ddk implementation */
25 #include "wdm.h"
26 #include "Device.h"
27 #include "endian_mgmt.h" /* FIXME */
28 #else /* win32 sdk implementation */
29 #include <windows.h>
30 #include "types.h"
31 #include "util.h"
32 #include "as10x_handle.h"
33 #include "endian_mgmt.h"
34 #endif
35#else /* all other cases */
36 #include <string.h>
37 #include "types.h"
38 #include "util.h"
39 #include "as10x_handle.h"
40 #include "endian_mgmt.h" /* FIXME */
41#endif /* __KERNEL__ */
42
43#include "as10x_types.h"
44#include "as10x_cmd.h"
45
46/**
47 \brief send turn on command to AS10x
48 \param phandle: pointer to AS10x handle
49 \return 0 when no error, < 0 in case of error.
50 \callgraph
51*/
52int as10x_cmd_turn_on(as10x_handle_t *phandle)
53{
54 int error;
55 struct as10x_cmd_t *pcmd, *prsp;
56
57 ENTER();
58
59 pcmd = phandle->cmd;
60 prsp = phandle->rsp;
61
62 /* prepare command */
63 as10x_cmd_build(pcmd,(++phandle->cmd_xid), sizeof(pcmd->body.turn_on.req));
64
65 /* fill command */
66 pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
67
68 /* send command */
69 if(phandle->ops->xfer_cmd) {
70 error = phandle->ops->xfer_cmd(
71 phandle,
72 (uint8_t *) pcmd,
73 sizeof(pcmd->body.turn_on.req) + HEADER_SIZE,
74 (uint8_t *) prsp,
75 sizeof(prsp->body.turn_on.rsp) + HEADER_SIZE);
76 }
77 else{
78 error = AS10X_CMD_ERROR;
79 }
80
81 if(error < 0) {
82 goto out;
83 }
84
85 /* parse response */
86 error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
87
88out:
89 LEAVE();
90 return(error);
91}
92
93/**
94 \brief send turn off command to AS10x
95 \param phandle: pointer to AS10x handle
96 \return 0 when no error, < 0 in case of error.
97 \callgraph
98*/
99int as10x_cmd_turn_off(as10x_handle_t *phandle)
100{
101 int error;
102 struct as10x_cmd_t *pcmd, *prsp;
103
104 ENTER();
105
106 pcmd = phandle->cmd;
107 prsp = phandle->rsp;
108
109 /* prepare command */
110 as10x_cmd_build(pcmd,(++phandle->cmd_xid),sizeof(pcmd->body.turn_off.req));
111
112 /* fill command */
113 pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
114
115 /* send command */
116 if(phandle->ops->xfer_cmd) {
117 error = phandle->ops->xfer_cmd(
118 phandle, (uint8_t *) pcmd,
119 sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
120 (uint8_t *) prsp,
121 sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
122 }
123 else{
124 error = AS10X_CMD_ERROR;
125 }
126
127 if(error < 0) {
128 goto out;
129 }
130
131 /* parse response */
132 error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
133
134out:
135 LEAVE();
136 return(error);
137}
138
139/**
140 \brief send set tune command to AS10x
141 \param phandle: pointer to AS10x handle
142 \param ptune: tune parameters
143 \return 0 when no error, < 0 in case of error.
144 \callgraph
145 */
146int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
147{
148 int error;
149 struct as10x_cmd_t *preq, *prsp;
150
151 ENTER();
152
153 preq = phandle->cmd;
154 prsp = phandle->rsp;
155
156 /* prepare command */
157 as10x_cmd_build(preq,(++phandle->cmd_xid),sizeof(preq->body.set_tune.req));
158
159 /* fill command */
160 preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
161 preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
162 preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
163 preq->body.set_tune.req.args.hier_select = ptune->hier_select;
164 preq->body.set_tune.req.args.constellation = ptune->constellation;
165 preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
166 preq->body.set_tune.req.args.interleaving_mode = ptune->interleaving_mode;
167 preq->body.set_tune.req.args.code_rate = ptune->code_rate;
168 preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
169 preq->body.set_tune.req.args.transmission_mode = ptune->transmission_mode;
170
171 /* send command */
172 if(phandle->ops->xfer_cmd) {
173 error = phandle->ops->xfer_cmd(phandle,
174 (uint8_t *) preq,
175 sizeof(preq->body.set_tune.req) + HEADER_SIZE,
176 (uint8_t *) prsp,
177 sizeof(prsp->body.set_tune.rsp) + HEADER_SIZE);
178 } else{
179 error = AS10X_CMD_ERROR;
180 }
181
182 if(error < 0) {
183 goto out;
184 }
185
186 /* parse response */
187 error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
188
189out:
190 LEAVE();
191 return(error);
192}
193
194/**
195 \brief send get tune status command to AS10x
196 \param phandle: pointer to AS10x handle
197 \param pstatus: pointer to updated status structure of the current tune
198 \return 0 when no error, < 0 in case of error.
199 \callgraph
200 */
201int as10x_cmd_get_tune_status(as10x_handle_t *phandle, struct as10x_tune_status *pstatus)
202{
203 int error;
204 struct as10x_cmd_t *preq, *prsp;
205
206 ENTER();
207
208 preq = phandle->cmd;
209 prsp = phandle->rsp;
210
211 /* prepare command */
212 as10x_cmd_build(preq,(++phandle->cmd_xid),
213 sizeof(preq->body.get_tune_status.req));
214
215 /* fill command */
216 preq->body.get_tune_status.req.proc_id =
217 cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
218
219 /* send command */
220 if (phandle->ops->xfer_cmd) {
221 error = phandle->ops->xfer_cmd(
222 phandle,
223 (uint8_t *) preq,
224 sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
225 (uint8_t *) prsp,
226 sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
227 }
228 else{
229 error = AS10X_CMD_ERROR;
230 }
231
232 if (error < 0) {
233 goto out;
234 }
235
236 /* parse response */
237 error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
238 if (error < 0) {
239 goto out;
240 }
241
242 /* Response OK -> get response data */
243 pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
244 pstatus->signal_strength =
245 le16_to_cpu(prsp->body.get_tune_status.rsp.sts.signal_strength);
246 pstatus->PER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.PER);
247 pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER);
248
249out:
250 LEAVE();
251 return(error);
252}
253
254/**
255 \brief send get TPS command to AS10x
256 \param phandle: pointer to AS10x handle
257 \param ptps: pointer to TPS parameters structure
258 \return 0 when no error, < 0 in case of error.
259 \callgraph
260 */
261int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
262{
263
264 int error;
265 struct as10x_cmd_t *pcmd, *prsp;
266
267 ENTER();
268
269 pcmd = phandle->cmd;
270 prsp = phandle->rsp;
271
272 /* prepare command */
273 as10x_cmd_build(pcmd, (++phandle->cmd_xid),sizeof(pcmd->body.get_tps.req));
274
275 /* fill command */
276 pcmd->body.get_tune_status.req.proc_id = cpu_to_le16(CONTROL_PROC_GETTPS);
277
278 /* send command */
279 if(phandle->ops->xfer_cmd) {
280 error = phandle->ops->xfer_cmd(phandle,
281 (uint8_t *) pcmd, sizeof(pcmd->body.get_tps.req) + HEADER_SIZE,
282 (uint8_t *) prsp, sizeof(prsp->body.get_tps.rsp) + HEADER_SIZE);
283 }
284 else{
285 error = AS10X_CMD_ERROR;
286 }
287
288 if(error < 0) {
289 goto out;
290 }
291
292 /* parse response */
293 error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
294 if (error < 0) {
295 goto out;
296 }
297
298 /* Response OK -> get response data */
299 ptps->constellation = prsp->body.get_tps.rsp.tps.constellation;
300 ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
301 ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
302 ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
303 ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
304 ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
305 ptps->transmission_mode = prsp->body.get_tps.rsp.tps.transmission_mode;
306 ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
307 ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
308 ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID);
309
310out:
311 LEAVE();
312 return(error);
313}
314
315/**
316 \brief send get demod stats command to AS10x
317 \param phandle: pointer to AS10x handle
318 \param pdemod_stats: pointer to demod stats parameters structure
319 \return 0 when no error, < 0 in case of error.
320 \callgraph
321*/
322int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
323 struct as10x_demod_stats *pdemod_stats)
324{
325 int error;
326 struct as10x_cmd_t *pcmd, *prsp;
327
328 ENTER();
329
330 pcmd = phandle->cmd;
331 prsp = phandle->rsp;
332
333 /* prepare command */
334 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
335 sizeof(pcmd->body.get_demod_stats.req));
336
337 /* fill command */
338 pcmd->body.get_demod_stats.req.proc_id =
339 cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
340
341 /* send command */
342 if(phandle->ops->xfer_cmd) {
343 error = phandle->ops->xfer_cmd(phandle,
344 (uint8_t *) pcmd,
345 sizeof(pcmd->body.get_demod_stats.req) + HEADER_SIZE,
346 (uint8_t *) prsp,
347 sizeof(prsp->body.get_demod_stats.rsp) + HEADER_SIZE);
348 }
349 else{
350 error = AS10X_CMD_ERROR;
351 }
352
353 if(error < 0) {
354 goto out;
355 }
356
357 /* parse response */
358 error = as10x_rsp_parse(prsp,CONTROL_PROC_GET_DEMOD_STATS_RSP);
359 if (error < 0) {
360 goto out;
361 }
362
363 /* Response OK -> get response data */
364 pdemod_stats->frame_count =
365 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.frame_count);
366 pdemod_stats->bad_frame_count =
367 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
368 pdemod_stats->bytes_fixed_by_rs =
369 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
370 pdemod_stats->mer =
371 le16_to_cpu(prsp->body.get_demod_stats.rsp.stats.mer);
372 pdemod_stats->has_started =
373 prsp->body.get_demod_stats.rsp.stats.has_started;
374
375out:
376 LEAVE();
377 return(error);
378}
379
380/**
381 \brief send get impulse response command to AS10x
382 \param phandle: pointer to AS10x handle
383 \param is_ready: pointer to value indicating when impulse
384 response data is ready
385 \return 0 when no error, < 0 in case of error.
386 \callgraph
387*/
388int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
389 uint8_t *is_ready)
390{
391 int error;
392 struct as10x_cmd_t *pcmd, *prsp;
393
394 ENTER();
395
396 pcmd = phandle->cmd;
397 prsp = phandle->rsp;
398
399 /* prepare command */
400 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
401 sizeof(pcmd->body.get_impulse_rsp.req));
402
403 /* fill command */
404 pcmd->body.get_impulse_rsp.req.proc_id =
405 cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
406
407 /* send command */
408 if(phandle->ops->xfer_cmd) {
409 error = phandle->ops->xfer_cmd(phandle,
410 (uint8_t *) pcmd,
411 sizeof(pcmd->body.get_impulse_rsp.req) + HEADER_SIZE,
412 (uint8_t *) prsp,
413 sizeof(prsp->body.get_impulse_rsp.rsp) + HEADER_SIZE);
414 }
415 else{
416 error = AS10X_CMD_ERROR;
417 }
418
419 if(error < 0) {
420 goto out;
421 }
422
423 /* parse response */
424 error = as10x_rsp_parse(prsp,CONTROL_PROC_GET_IMPULSE_RESP_RSP);
425 if (error < 0) {
426 goto out;
427 }
428
429 /* Response OK -> get response data */
430 *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
431
432out:
433 LEAVE();
434 return(error);
435}
436
437
438
439/**
440 \brief build AS10x command header
441 \param pcmd: pointer to AS10x command buffer
442 \param xid: sequence id of the command
443 \param cmd_len: lenght of the command
444 \return -
445 \callgraph
446*/
447void as10x_cmd_build(struct as10x_cmd_t *pcmd,
448 uint16_t xid, uint16_t cmd_len)
449{
450 pcmd->header.req_id = cpu_to_le16(xid);
451 pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
452 pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
453 pcmd->header.data_len = cpu_to_le16(cmd_len);
454}
455
456/**
457 \brief Parse command response
458 \param pcmd: pointer to AS10x command buffer
459 \param cmd_seqid: sequence id of the command
460 \param cmd_len: lenght of the command
461 \return 0 when no error, < 0 in case of error
462 \callgraph
463*/
464int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
465{
466 int error;
467
468 /* extract command error code */
469 error = prsp->body.common.rsp.error;
470
471 if((error == 0) && (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
472 return 0;
473 }
474
475 return AS10X_CMD_ERROR;
476}
477
478
diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h
new file mode 100644
index 00000000000..01a716380e0
--- /dev/null
+++ b/drivers/staging/media/as102/as10x_cmd.h
@@ -0,0 +1,540 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#ifndef _AS10X_CMD_H_
20#define _AS10X_CMD_H_
21
22#ifdef __KERNEL__
23#include <linux/kernel.h>
24#endif
25
26#include "as10x_types.h"
27
28/*********************************/
29/* MACRO DEFINITIONS */
30/*********************************/
31#define AS10X_CMD_ERROR -1
32
33#define SERVICE_PROG_ID 0x0002
34#define SERVICE_PROG_VERSION 0x0001
35
36#define HIER_NONE 0x00
37#define HIER_LOW_PRIORITY 0x01
38
39#define HEADER_SIZE (sizeof(struct as10x_cmd_header_t))
40
41/* context request types */
42#define GET_CONTEXT_DATA 1
43#define SET_CONTEXT_DATA 2
44
45/* ODSP suspend modes */
46#define CFG_MODE_ODSP_RESUME 0
47#define CFG_MODE_ODSP_SUSPEND 1
48
49/* Dump memory size */
50#define DUMP_BLOCK_SIZE_MAX 0x20
51
52/*********************************/
53/* TYPE DEFINITION */
54/*********************************/
55typedef enum {
56 CONTROL_PROC_TURNON = 0x0001,
57 CONTROL_PROC_TURNON_RSP = 0x0100,
58 CONTROL_PROC_SET_REGISTER = 0x0002,
59 CONTROL_PROC_SET_REGISTER_RSP = 0x0200,
60 CONTROL_PROC_GET_REGISTER = 0x0003,
61 CONTROL_PROC_GET_REGISTER_RSP = 0x0300,
62 CONTROL_PROC_SETTUNE = 0x000A,
63 CONTROL_PROC_SETTUNE_RSP = 0x0A00,
64 CONTROL_PROC_GETTUNESTAT = 0x000B,
65 CONTROL_PROC_GETTUNESTAT_RSP = 0x0B00,
66 CONTROL_PROC_GETTPS = 0x000D,
67 CONTROL_PROC_GETTPS_RSP = 0x0D00,
68 CONTROL_PROC_SETFILTER = 0x000E,
69 CONTROL_PROC_SETFILTER_RSP = 0x0E00,
70 CONTROL_PROC_REMOVEFILTER = 0x000F,
71 CONTROL_PROC_REMOVEFILTER_RSP = 0x0F00,
72 CONTROL_PROC_GET_IMPULSE_RESP = 0x0012,
73 CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200,
74 CONTROL_PROC_START_STREAMING = 0x0013,
75 CONTROL_PROC_START_STREAMING_RSP = 0x1300,
76 CONTROL_PROC_STOP_STREAMING = 0x0014,
77 CONTROL_PROC_STOP_STREAMING_RSP = 0x1400,
78 CONTROL_PROC_GET_DEMOD_STATS = 0x0015,
79 CONTROL_PROC_GET_DEMOD_STATS_RSP = 0x1500,
80 CONTROL_PROC_ELNA_CHANGE_MODE = 0x0016,
81 CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600,
82 CONTROL_PROC_ODSP_CHANGE_MODE = 0x0017,
83 CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700,
84 CONTROL_PROC_AGC_CHANGE_MODE = 0x0018,
85 CONTROL_PROC_AGC_CHANGE_MODE_RSP = 0x1800,
86
87 CONTROL_PROC_CONTEXT = 0x00FC,
88 CONTROL_PROC_CONTEXT_RSP = 0xFC00,
89 CONTROL_PROC_DUMP_MEMORY = 0x00FD,
90 CONTROL_PROC_DUMP_MEMORY_RSP = 0xFD00,
91 CONTROL_PROC_DUMPLOG_MEMORY = 0x00FE,
92 CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00,
93 CONTROL_PROC_TURNOFF = 0x00FF,
94 CONTROL_PROC_TURNOFF_RSP = 0xFF00
95} control_proc;
96
97
98#pragma pack(1)
99typedef union {
100 /* request */
101 struct {
102 /* request identifier */
103 uint16_t proc_id;
104 } req;
105 /* response */
106 struct {
107 /* response identifier */
108 uint16_t proc_id;
109 /* error */
110 uint8_t error;
111 } rsp;
112} TURN_ON;
113
114typedef union {
115 /* request */
116 struct {
117 /* request identifier */
118 uint16_t proc_id;
119 } req;
120 /* response */
121 struct {
122 /* response identifier */
123 uint16_t proc_id;
124 /* error */
125 uint8_t err;
126 } rsp;
127} TURN_OFF;
128
129typedef union {
130 /* request */
131 struct {
132 /* request identifier */
133 uint16_t proc_id;
134 /* tune params */
135 struct as10x_tune_args args;
136 } req;
137 /* response */
138 struct {
139 /* response identifier */
140 uint16_t proc_id;
141 /* response error */
142 uint8_t error;
143 } rsp;
144} SET_TUNE;
145
146typedef union {
147 /* request */
148 struct {
149 /* request identifier */
150 uint16_t proc_id;
151 } req;
152 /* response */
153 struct {
154 /* response identifier */
155 uint16_t proc_id;
156 /* response error */
157 uint8_t error;
158 /* tune status */
159 struct as10x_tune_status sts;
160 } rsp;
161} GET_TUNE_STATUS;
162
163typedef union {
164 /* request */
165 struct {
166 /* request identifier */
167 uint16_t proc_id;
168 } req;
169 /* response */
170 struct {
171 /* response identifier */
172 uint16_t proc_id;
173 /* response error */
174 uint8_t error;
175 /* tps details */
176 struct as10x_tps tps;
177 } rsp;
178} GET_TPS;
179
180typedef union {
181 /* request */
182 struct {
183 /* request identifier */
184 uint16_t proc_id;
185 } req;
186 /* response */
187 struct {
188 /* response identifier */
189 uint16_t proc_id;
190 /* response error */
191 uint8_t error;
192 } rsp;
193} COMMON;
194
195typedef union {
196 /* request */
197 struct {
198 /* request identifier */
199 uint16_t proc_id;
200 /* PID to filter */
201 uint16_t pid;
202 /* stream type (MPE, PSI/SI or PES )*/
203 uint8_t stream_type;
204 /* PID index in filter table */
205 uint8_t idx;
206 } req;
207 /* response */
208 struct {
209 /* response identifier */
210 uint16_t proc_id;
211 /* response error */
212 uint8_t error;
213 /* Filter id */
214 uint8_t filter_id;
215 } rsp;
216} ADD_PID_FILTER;
217
218typedef union {
219 /* request */
220 struct {
221 /* request identifier */
222 uint16_t proc_id;
223 /* PID to remove */
224 uint16_t pid;
225 } req;
226 /* response */
227 struct {
228 /* response identifier */
229 uint16_t proc_id;
230 /* response error */
231 uint8_t error;
232 } rsp;
233} DEL_PID_FILTER;
234
235typedef union {
236 /* request */
237 struct {
238 /* request identifier */
239 uint16_t proc_id;
240 } req;
241 /* response */
242 struct {
243 /* response identifier */
244 uint16_t proc_id;
245 /* error */
246 uint8_t error;
247 } rsp;
248} START_STREAMING;
249
250typedef union {
251 /* request */
252 struct {
253 /* request identifier */
254 uint16_t proc_id;
255 } req;
256 /* response */
257 struct {
258 /* response identifier */
259 uint16_t proc_id;
260 /* error */
261 uint8_t error;
262 } rsp;
263} STOP_STREAMING;
264
265typedef union {
266 /* request */
267 struct {
268 /* request identifier */
269 uint16_t proc_id;
270 } req;
271 /* response */
272 struct {
273 /* response identifier */
274 uint16_t proc_id;
275 /* error */
276 uint8_t error;
277 /* demod stats */
278 struct as10x_demod_stats stats;
279 } rsp;
280} GET_DEMOD_STATS;
281
282typedef union {
283 /* request */
284 struct {
285 /* request identifier */
286 uint16_t proc_id;
287 } req;
288 /* response */
289 struct {
290 /* response identifier */
291 uint16_t proc_id;
292 /* error */
293 uint8_t error;
294 /* impulse response ready */
295 uint8_t is_ready;
296 } rsp;
297} GET_IMPULSE_RESP;
298
299typedef union {
300 /* request */
301 struct {
302 /* request identifier */
303 uint16_t proc_id;
304 /* value to write (for set context)*/
305 struct as10x_register_value reg_val;
306 /* context tag */
307 uint16_t tag;
308 /* context request type */
309 uint16_t type;
310 } req;
311 /* response */
312 struct {
313 /* response identifier */
314 uint16_t proc_id;
315 /* value read (for get context) */
316 struct as10x_register_value reg_val;
317 /* context request type */
318 uint16_t type;
319 /* error */
320 uint8_t error;
321 } rsp;
322} FW_CONTEXT;
323
324typedef union {
325 /* request */
326 struct {
327 /* response identifier */
328 uint16_t proc_id;
329 /* register description */
330 struct as10x_register_addr reg_addr;
331 /* register content */
332 struct as10x_register_value reg_val;
333 } req;
334 /* response */
335 struct {
336 /* response identifier */
337 uint16_t proc_id;
338 /* error */
339 uint8_t error;
340 } rsp;
341} SET_REGISTER;
342
343typedef union {
344 /* request */
345 struct {
346 /* response identifier */
347 uint16_t proc_id;
348 /* register description */
349 struct as10x_register_addr reg_addr;
350 } req;
351 /* response */
352 struct {
353 /* response identifier */
354 uint16_t proc_id;
355 /* error */
356 uint8_t error;
357 /* register content */
358 struct as10x_register_value reg_val;
359 } rsp;
360} GET_REGISTER;
361
362typedef union {
363 /* request */
364 struct {
365 /* request identifier */
366 uint16_t proc_id;
367 /* mode */
368 uint8_t mode;
369 } req;
370 /* response */
371 struct {
372 /* response identifier */
373 uint16_t proc_id;
374 /* error */
375 uint8_t error;
376 } rsp;
377} CFG_CHANGE_MODE;
378
379struct as10x_cmd_header_t {
380 uint16_t req_id;
381 uint16_t prog;
382 uint16_t version;
383 uint16_t data_len;
384};
385
386#define DUMP_BLOCK_SIZE 16
387typedef union {
388 /* request */
389 struct {
390 /* request identifier */
391 uint16_t proc_id;
392 /* dump memory type request */
393 uint8_t dump_req;
394 /* register description */
395 struct as10x_register_addr reg_addr;
396 /* nb blocks to read */
397 uint16_t num_blocks;
398 } req;
399 /* response */
400 struct {
401 /* response identifier */
402 uint16_t proc_id;
403 /* error */
404 uint8_t error;
405 /* dump response */
406 uint8_t dump_rsp;
407 /* data */
408 union {
409 uint8_t data8[DUMP_BLOCK_SIZE];
410 uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
411 uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
412 } u;
413 } rsp;
414} DUMP_MEMORY;
415
416typedef union {
417 struct {
418 /* request identifier */
419 uint16_t proc_id;
420 /* dump memory type request */
421 uint8_t dump_req;
422 } req;
423 struct {
424 /* request identifier */
425 uint16_t proc_id;
426 /* error */
427 uint8_t error;
428 /* dump response */
429 uint8_t dump_rsp;
430 /* dump data */
431 uint8_t data[DUMP_BLOCK_SIZE];
432 } rsp;
433} DUMPLOG_MEMORY;
434
435typedef union {
436 /* request */
437 struct {
438 uint16_t proc_id;
439 uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */];
440 } req;
441 /* response */
442 struct {
443 uint16_t proc_id;
444 uint8_t error;
445 uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */
446 - 2 /* proc_id */ - 1 /* rc */];
447 } rsp;
448} RAW_DATA;
449
450struct as10x_cmd_t {
451 /* header */
452 struct as10x_cmd_header_t header;
453 /* body */
454 union {
455 TURN_ON turn_on;
456 TURN_OFF turn_off;
457 SET_TUNE set_tune;
458 GET_TUNE_STATUS get_tune_status;
459 GET_TPS get_tps;
460 COMMON common;
461 ADD_PID_FILTER add_pid_filter;
462 DEL_PID_FILTER del_pid_filter;
463 START_STREAMING start_streaming;
464 STOP_STREAMING stop_streaming;
465 GET_DEMOD_STATS get_demod_stats;
466 GET_IMPULSE_RESP get_impulse_rsp;
467 FW_CONTEXT context;
468 SET_REGISTER set_register;
469 GET_REGISTER get_register;
470 CFG_CHANGE_MODE cfg_change_mode;
471 DUMP_MEMORY dump_memory;
472 DUMPLOG_MEMORY dumplog_memory;
473 RAW_DATA raw_data;
474 } body;
475};
476
477struct as10x_token_cmd_t {
478 /* token cmd */
479 struct as10x_cmd_t c;
480 /* token response */
481 struct as10x_cmd_t r;
482};
483#pragma pack()
484
485
486/**************************/
487/* FUNCTION DECLARATION */
488/**************************/
489
490void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id,
491 uint16_t cmd_len);
492int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id);
493
494#ifdef __cplusplus
495extern "C" {
496#endif
497
498/* as10x cmd */
499int as10x_cmd_turn_on(as10x_handle_t *phandle);
500int as10x_cmd_turn_off(as10x_handle_t *phandle);
501
502int as10x_cmd_set_tune(as10x_handle_t *phandle,
503 struct as10x_tune_args *ptune);
504
505int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
506 struct as10x_tune_status *pstatus);
507
508int as10x_cmd_get_tps(as10x_handle_t *phandle,
509 struct as10x_tps *ptps);
510
511int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
512 struct as10x_demod_stats *pdemod_stats);
513
514int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
515 uint8_t *is_ready);
516
517/* as10x cmd stream */
518int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
519 struct as10x_ts_filter *filter);
520int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
521 uint16_t pid_value);
522
523int as10x_cmd_start_streaming(as10x_handle_t *phandle);
524int as10x_cmd_stop_streaming(as10x_handle_t *phandle);
525
526/* as10x cmd cfg */
527int as10x_cmd_set_context(as10x_handle_t *phandle,
528 uint16_t tag,
529 uint32_t value);
530int as10x_cmd_get_context(as10x_handle_t *phandle,
531 uint16_t tag,
532 uint32_t *pvalue);
533
534int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode);
535int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id);
536#ifdef __cplusplus
537}
538#endif
539#endif
540/* EOF - vim: set textwidth=80 ts=3 sw=3 sts=3 et: */
diff --git a/drivers/staging/media/as102/as10x_cmd_cfg.c b/drivers/staging/media/as102/as10x_cmd_cfg.c
new file mode 100644
index 00000000000..e3a0f90936d
--- /dev/null
+++ b/drivers/staging/media/as102/as10x_cmd_cfg.c
@@ -0,0 +1,239 @@
1/**
2
3 \file as10x_cmd_cfg.c
4
5 \version $Id$
6
7 \author: S. Martinelli
8
9 ----------------------------------------------------------------------------\n
10 (c) Copyright Abilis Systems SARL 2005-2009 All rigths reserved \n
11 www.abilis.com \n
12 ----------------------------------------------------------------------------\n
13
14 \brief AS10x API, configuration services
15
16 AS10x cmd management: build command buffer, send command through
17 selected port and wait for the response when required.
18
19*/
20
21#if defined(LINUX) && defined(__KERNEL__) /* linux kernel implementation */
22#include <linux/kernel.h>
23#include "as102_drv.h"
24#elif defined(WIN32)
25 #if defined(__BUILDMACHINE__) && (__BUILDMACHINE__ == WinDDK) /* win32 ddk implementation */
26 #include "wdm.h"
27 #include "Device.h"
28 #include "endian_mgmt.h" /* FIXME */
29 #else /* win32 sdk implementation */
30 #include <windows.h>
31 #include "types.h"
32 #include "util.h"
33 #include "as10x_handle.h"
34 #include "endian_mgmt.h"
35 #endif
36#else /* all other cases */
37 #include <string.h>
38 #include "types.h"
39 #include "util.h"
40 #include "as10x_handle.h"
41 #include "endian_mgmt.h" /* FIXME */
42#endif /* __KERNEL__ */
43
44#include "as10x_types.h"
45#include "as10x_cmd.h"
46
47/***************************/
48/* FUNCTION DEFINITION */
49/***************************/
50
51/**
52 \brief send get context command to AS10x
53 \param phandle: pointer to AS10x handle
54 \param tag: context tag
55 \param pvalue: pointer where to store context value read
56 \return 0 when no error, < 0 in case of error.
57 \callgraph
58*/
59int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
60 uint32_t *pvalue)
61{
62 int error;
63 struct as10x_cmd_t *pcmd, *prsp;
64
65 ENTER();
66
67 pcmd = phandle->cmd;
68 prsp = phandle->rsp;
69
70 /* prepare command */
71 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
72 sizeof(pcmd->body.context.req));
73
74 /* fill command */
75 pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
76 pcmd->body.context.req.tag = cpu_to_le16(tag);
77 pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA);
78
79 /* send command */
80 if(phandle->ops->xfer_cmd) {
81 error = phandle->ops->xfer_cmd(phandle,
82 (uint8_t *) pcmd,
83 sizeof(pcmd->body.context.req) + HEADER_SIZE,
84 (uint8_t *) prsp,
85 sizeof(prsp->body.context.rsp) + HEADER_SIZE);
86 }
87 else{
88 error = AS10X_CMD_ERROR;
89 }
90
91 if(error < 0) {
92 goto out;
93 }
94
95 /* parse response: context command do not follow the common response */
96 /* structure -> specific handling response parse required */
97 error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);
98
99 if(error == 0) {
100 /* Response OK -> get response data */
101 *pvalue = le32_to_cpu(prsp->body.context.rsp.reg_val.u.value32);
102 /* value returned is always a 32-bit value */
103 }
104
105out:
106 LEAVE();
107 return(error);
108}
109
110/**
111 \brief send set context command to AS10x
112 \param phandle: pointer to AS10x handle
113 \param tag: context tag
114 \param value: value to set in context
115 \return 0 when no error, < 0 in case of error.
116 \callgraph
117*/
118int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
119 uint32_t value)
120{
121 int error;
122 struct as10x_cmd_t *pcmd, *prsp;
123
124 ENTER();
125
126 pcmd = phandle->cmd;
127 prsp = phandle->rsp;
128
129 /* prepare command */
130 as10x_cmd_build(pcmd,(++phandle->cmd_xid),sizeof(pcmd->body.context.req));
131
132 /* fill command */
133 pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
134 /* pcmd->body.context.req.reg_val.mode initialization is not required */
135 pcmd->body.context.req.reg_val.u.value32 = cpu_to_le32(value);
136 pcmd->body.context.req.tag = cpu_to_le16(tag);
137 pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA);
138
139 /* send command */
140 if(phandle->ops->xfer_cmd){
141 error = phandle->ops->xfer_cmd(phandle,
142 (uint8_t *) pcmd,
143 sizeof(pcmd->body.context.req) + HEADER_SIZE,
144 (uint8_t *) prsp,
145 sizeof(prsp->body.context.rsp) + HEADER_SIZE);
146 }
147 else{
148 error = AS10X_CMD_ERROR;
149 }
150
151 if(error < 0) {
152 goto out;
153 }
154
155 /* parse response: context command do not follow the common response */
156 /* structure -> specific handling response parse required */
157 error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);
158
159out:
160 LEAVE();
161 return(error);
162}
163
164/**
165 \brief send eLNA change mode command to AS10x
166 \param phandle: pointer to AS10x handle
167 \param tag: context tag
168 \param mode: mode selected:
169 - ON : 0x0 => eLNA always ON
170 - OFF : 0x1 => eLNA always OFF
171 - AUTO : 0x2 => eLNA follow hysteresis parameters to be
172 ON or OFF
173 \return 0 when no error, < 0 in case of error.
174 \callgraph
175*/
176int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode)
177{
178 int error;
179 struct as10x_cmd_t *pcmd, *prsp;
180
181 ENTER();
182
183 pcmd = phandle->cmd;
184 prsp = phandle->rsp;
185
186 /* prepare command */
187 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
188 sizeof(pcmd->body.cfg_change_mode.req));
189
190 /* fill command */
191 pcmd->body.cfg_change_mode.req.proc_id =
192 cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE);
193 pcmd->body.cfg_change_mode.req.mode = mode;
194
195 /* send command */
196 if(phandle->ops->xfer_cmd){
197 error = phandle->ops->xfer_cmd(phandle,
198 (uint8_t *) pcmd,
199 sizeof(pcmd->body.cfg_change_mode.req) + HEADER_SIZE,
200 (uint8_t *) prsp,
201 sizeof(prsp->body.cfg_change_mode.rsp) + HEADER_SIZE);
202 }
203 else{
204 error = AS10X_CMD_ERROR;
205 }
206
207 if(error < 0) {
208 goto out;
209 }
210
211 /* parse response */
212 error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP);
213
214out:
215 LEAVE();
216 return(error);
217}
218
219/**
220 \brief Parse context command response. Since this command does not follow
221 the common response, a specific parse function is required.
222 \param prsp: pointer to AS10x command response buffer
223 \param proc_id: id of the command
224 \return 0 when no error, < 0 in case of error.
225 ABILIS_RC_NOK
226 \callgraph
227*/
228int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id) {
229
230 int err;
231
232 err = prsp->body.context.rsp.error;
233
234 if((err == 0) &&
235 (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) {
236 return 0;
237 }
238 return AS10X_CMD_ERROR;
239}
diff --git a/drivers/staging/media/as102/as10x_cmd_stream.c b/drivers/staging/media/as102/as10x_cmd_stream.c
new file mode 100644
index 00000000000..4dfacf464ed
--- /dev/null
+++ b/drivers/staging/media/as102/as10x_cmd_stream.c
@@ -0,0 +1,256 @@
1/**
2
3 \file as10x_cmd_stream.c
4
5 \version $Id$
6
7 \author: S. Martinelli
8
9 ----------------------------------------------------------------------------\n
10 (c) Copyright Abilis Systems SARL 2005-2009 All rigths reserved \n
11 www.abilis.com \n
12 ----------------------------------------------------------------------------\n
13
14 \brief AS10x CMD, stream services
15
16 AS10x CMD management: build command buffer, send command through
17 selected port and wait for the response when required.
18
19*/
20
21
22#if defined(LINUX) && defined(__KERNEL__) /* linux kernel implementation */
23#include <linux/kernel.h>
24#include "as102_drv.h"
25#elif defined(WIN32)
26 #if defined(DDK) /* win32 ddk implementation */
27 #include "wdm.h"
28 #include "Device.h"
29 #include "endian_mgmt.h" /* FIXME */
30 #else /* win32 sdk implementation */
31 #include <windows.h>
32 #include "types.h"
33 #include "util.h"
34 #include "as10x_handle.h"
35 #include "endian_mgmt.h"
36 #endif
37#else /* all other cases */
38 #include <string.h>
39 #include "types.h"
40 #include "util.h"
41 #include "as10x_handle.h"
42 #include "endian_mgmt.h" /* FIXME */
43#endif /* __KERNEL__ */
44
45#include "as10x_cmd.h"
46
47
48/**
49 \brief send add filter command to AS10x
50 \param phandle: pointer to AS10x handle
51 \param filter: TSFilter filter for DVB-T
52 \param pfilter_handle: pointer where to store filter handle
53 \return 0 when no error, < 0 in case of error.
54 \callgraph
55*/
56int as10x_cmd_add_PID_filter(as10x_handle_t* phandle,
57 struct as10x_ts_filter *filter) {
58 int error;
59 struct as10x_cmd_t *pcmd, *prsp;
60
61 ENTER();
62
63 pcmd = phandle->cmd;
64 prsp = phandle->rsp;
65
66 /* prepare command */
67 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
68 sizeof(pcmd->body.add_pid_filter.req));
69
70 /* fill command */
71 pcmd->body.add_pid_filter.req.proc_id = cpu_to_le16(CONTROL_PROC_SETFILTER);
72 pcmd->body.add_pid_filter.req.pid = cpu_to_le16(filter->pid);
73 pcmd->body.add_pid_filter.req.stream_type = filter->type;
74
75 if(filter->idx < 16)
76 pcmd->body.add_pid_filter.req.idx = filter->idx;
77 else
78 pcmd->body.add_pid_filter.req.idx = 0xFF;
79
80 /* send command */
81 if(phandle->ops->xfer_cmd) {
82 error = phandle->ops->xfer_cmd(phandle,
83 (uint8_t *) pcmd,
84 sizeof(pcmd->body.add_pid_filter.req) + HEADER_SIZE,
85 (uint8_t *) prsp,
86 sizeof(prsp->body.add_pid_filter.rsp) + HEADER_SIZE);
87 }
88 else{
89 error = AS10X_CMD_ERROR;
90 }
91
92 if(error < 0) {
93 goto out;
94 }
95
96 /* parse response */
97 error = as10x_rsp_parse(prsp, CONTROL_PROC_SETFILTER_RSP);
98
99 if(error == 0) {
100 /* Response OK -> get response data */
101 filter->idx = prsp->body.add_pid_filter.rsp.filter_id;
102 }
103
104out:
105 LEAVE();
106 return(error);
107}
108
109/**
110 \brief Send delete filter command to AS10x
111 \param phandle: pointer to AS10x handle
112 \param filter_handle: filter handle
113 \return 0 when no error, < 0 in case of error.
114 \callgraph
115*/
116int as10x_cmd_del_PID_filter(as10x_handle_t* phandle,
117 uint16_t pid_value)
118{
119
120 int error;
121 struct as10x_cmd_t *pcmd, *prsp;
122
123 ENTER();
124
125 pcmd = phandle->cmd;
126 prsp = phandle->rsp;
127
128 /* prepare command */
129 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
130 sizeof(pcmd->body.del_pid_filter.req));
131
132 /* fill command */
133 pcmd->body.del_pid_filter.req.proc_id = cpu_to_le16(CONTROL_PROC_REMOVEFILTER);
134 pcmd->body.del_pid_filter.req.pid = cpu_to_le16(pid_value);
135
136 /* send command */
137 if(phandle->ops->xfer_cmd){
138 error = phandle->ops->xfer_cmd(phandle,
139 (uint8_t *) pcmd,
140 sizeof(pcmd->body.del_pid_filter.req) + HEADER_SIZE,
141 (uint8_t *) prsp,
142 sizeof(prsp->body.del_pid_filter.rsp) + HEADER_SIZE);
143 }
144 else{
145 error = AS10X_CMD_ERROR;
146 }
147
148 if(error < 0) {
149 goto out;
150 }
151
152 /* parse response */
153 error = as10x_rsp_parse(prsp, CONTROL_PROC_REMOVEFILTER_RSP);
154
155out:
156 LEAVE();
157 return(error);
158}
159
160/**
161 \brief Send start streaming command to AS10x
162 \param phandle: pointer to AS10x handle
163 \return 0 when no error, < 0 in case of error. 
164 \callgraph
165*/
166int as10x_cmd_start_streaming(as10x_handle_t* phandle)
167{
168 int error;
169 struct as10x_cmd_t *pcmd, *prsp;
170
171 ENTER();
172
173 pcmd = phandle->cmd;
174 prsp = phandle->rsp;
175
176 /* prepare command */
177 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
178 sizeof(pcmd->body.start_streaming.req));
179
180 /* fill command */
181 pcmd->body.start_streaming.req.proc_id =
182 cpu_to_le16(CONTROL_PROC_START_STREAMING);
183
184 /* send command */
185 if(phandle->ops->xfer_cmd){
186 error = phandle->ops->xfer_cmd(phandle,
187 (uint8_t *) pcmd,
188 sizeof(pcmd->body.start_streaming.req) + HEADER_SIZE,
189 (uint8_t *) prsp,
190 sizeof(prsp->body.start_streaming.rsp) + HEADER_SIZE);
191 }
192 else{
193 error = AS10X_CMD_ERROR;
194 }
195
196 if(error < 0) {
197 goto out;
198 }
199
200 /* parse response */
201 error = as10x_rsp_parse(prsp, CONTROL_PROC_START_STREAMING_RSP);
202
203out:
204 LEAVE();
205 return(error);
206}
207
208/**
209 \brief Send stop streaming command to AS10x
210 \param phandle: pointer to AS10x handle
211 \return 0 when no error, < 0 in case of error. 
212 \callgraph
213*/
214int as10x_cmd_stop_streaming(as10x_handle_t* phandle)
215{
216 int8_t error;
217 struct as10x_cmd_t *pcmd, *prsp;
218
219 ENTER();
220
221 pcmd = phandle->cmd;
222 prsp = phandle->rsp;
223
224 /* prepare command */
225 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
226 sizeof(pcmd->body.stop_streaming.req));
227
228 /* fill command */
229 pcmd->body.stop_streaming.req.proc_id =
230 cpu_to_le16(CONTROL_PROC_STOP_STREAMING);
231
232 /* send command */
233 if(phandle->ops->xfer_cmd){
234 error = phandle->ops->xfer_cmd(phandle,
235 (uint8_t *) pcmd,
236 sizeof(pcmd->body.stop_streaming.req) + HEADER_SIZE,
237 (uint8_t *) prsp,
238 sizeof(prsp->body.stop_streaming.rsp) + HEADER_SIZE);
239 }
240 else{
241 error = AS10X_CMD_ERROR;
242 }
243
244 if(error < 0) {
245 goto out;
246 }
247
248 /* parse response */
249 error = as10x_rsp_parse(prsp, CONTROL_PROC_STOP_STREAMING_RSP);
250
251out:
252 LEAVE();
253 return(error);
254}
255
256
diff --git a/drivers/staging/media/as102/as10x_handle.h b/drivers/staging/media/as102/as10x_handle.h
new file mode 100644
index 00000000000..4f01a76e982
--- /dev/null
+++ b/drivers/staging/media/as102/as10x_handle.h
@@ -0,0 +1,58 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#ifdef __KERNEL__
20struct as102_bus_adapter_t;
21struct as102_dev_t;
22
23#define as10x_handle_t struct as102_bus_adapter_t
24#include "as10x_cmd.h"
25
26/* values for "mode" field */
27#define REGMODE8 8
28#define REGMODE16 16
29#define REGMODE32 32
30
31struct as102_priv_ops_t {
32 int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap,
33 unsigned char *buf, int buflen, int swap32);
34
35 int (*send_cmd) (struct as102_bus_adapter_t *bus_adap,
36 unsigned char *buf, int buflen);
37
38 int (*xfer_cmd) (struct as102_bus_adapter_t *bus_adap,
39 unsigned char *send_buf, int send_buf_len,
40 unsigned char *recv_buf, int recv_buf_len);
41/*
42 int (*pid_filter) (struct as102_bus_adapter_t *bus_adap,
43 int index, u16 pid, int onoff);
44*/
45 int (*start_stream) (struct as102_dev_t *dev);
46 void (*stop_stream) (struct as102_dev_t *dev);
47
48 int (*reset_target) (struct as102_bus_adapter_t *bus_adap);
49
50 int (*read_write)(struct as102_bus_adapter_t *bus_adap, uint8_t mode,
51 uint32_t rd_addr, uint16_t rd_len,
52 uint32_t wr_addr, uint16_t wr_len);
53
54 int (*as102_read_ep2) (struct as102_bus_adapter_t *bus_adap,
55 unsigned char *recv_buf,
56 int recv_buf_len);
57};
58#endif
diff --git a/drivers/staging/media/as102/as10x_types.h b/drivers/staging/media/as102/as10x_types.h
new file mode 100644
index 00000000000..3dedb3c1420
--- /dev/null
+++ b/drivers/staging/media/as102/as10x_types.h
@@ -0,0 +1,198 @@
1/*
2 * Abilis Systems Single DVB-T Receiver
3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * 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#ifndef _AS10X_TYPES_H_
20#define _AS10X_TYPES_H_
21
22#include "as10x_handle.h"
23
24/*********************************/
25/* MACRO DEFINITIONS */
26/*********************************/
27
28/* bandwidth constant values */
29#define BW_5_MHZ 0x00
30#define BW_6_MHZ 0x01
31#define BW_7_MHZ 0x02
32#define BW_8_MHZ 0x03
33
34/* hierarchy priority selection values */
35#define HIER_NO_PRIORITY 0x00
36#define HIER_LOW_PRIORITY 0x01
37#define HIER_HIGH_PRIORITY 0x02
38
39/* constellation available values */
40#define CONST_QPSK 0x00
41#define CONST_QAM16 0x01
42#define CONST_QAM64 0x02
43#define CONST_UNKNOWN 0xFF
44
45/* hierarchy available values */
46#define HIER_NONE 0x00
47#define HIER_ALPHA_1 0x01
48#define HIER_ALPHA_2 0x02
49#define HIER_ALPHA_4 0x03
50#define HIER_UNKNOWN 0xFF
51
52/* interleaving available values */
53#define INTLV_NATIVE 0x00
54#define INTLV_IN_DEPTH 0x01
55#define INTLV_UNKNOWN 0xFF
56
57/* code rate available values */
58#define CODE_RATE_1_2 0x00
59#define CODE_RATE_2_3 0x01
60#define CODE_RATE_3_4 0x02
61#define CODE_RATE_5_6 0x03
62#define CODE_RATE_7_8 0x04
63#define CODE_RATE_UNKNOWN 0xFF
64
65/* guard interval available values */
66#define GUARD_INT_1_32 0x00
67#define GUARD_INT_1_16 0x01
68#define GUARD_INT_1_8 0x02
69#define GUARD_INT_1_4 0x03
70#define GUARD_UNKNOWN 0xFF
71
72/* transmission mode available values */
73#define TRANS_MODE_2K 0x00
74#define TRANS_MODE_8K 0x01
75#define TRANS_MODE_4K 0x02
76#define TRANS_MODE_UNKNOWN 0xFF
77
78/* DVBH signalling available values */
79#define TIMESLICING_PRESENT 0x01
80#define MPE_FEC_PRESENT 0x02
81
82/* tune state available */
83#define TUNE_STATUS_NOT_TUNED 0x00
84#define TUNE_STATUS_IDLE 0x01
85#define TUNE_STATUS_LOCKING 0x02
86#define TUNE_STATUS_SIGNAL_DVB_OK 0x03
87#define TUNE_STATUS_STREAM_DETECTED 0x04
88#define TUNE_STATUS_STREAM_TUNED 0x05
89#define TUNE_STATUS_ERROR 0xFF
90
91/* available TS FID filter types */
92#define TS_PID_TYPE_TS 0
93#define TS_PID_TYPE_PSI_SI 1
94#define TS_PID_TYPE_MPE 2
95
96/* number of echos available */
97#define MAX_ECHOS 15
98
99/* Context types */
100#define CONTEXT_LNA 1010
101#define CONTEXT_ELNA_HYSTERESIS 4003
102#define CONTEXT_ELNA_GAIN 4004
103#define CONTEXT_MER_THRESHOLD 5005
104#define CONTEXT_MER_OFFSET 5006
105#define CONTEXT_IR_STATE 7000
106#define CONTEXT_TSOUT_MSB_FIRST 7004
107#define CONTEXT_TSOUT_FALLING_EDGE 7005
108
109/* Configuration modes */
110#define CFG_MODE_ON 0
111#define CFG_MODE_OFF 1
112#define CFG_MODE_AUTO 2
113
114#pragma pack(1)
115struct as10x_tps {
116 uint8_t constellation;
117 uint8_t hierarchy;
118 uint8_t interleaving_mode;
119 uint8_t code_rate_HP;
120 uint8_t code_rate_LP;
121 uint8_t guard_interval;
122 uint8_t transmission_mode;
123 uint8_t DVBH_mask_HP;
124 uint8_t DVBH_mask_LP;
125 uint16_t cell_ID;
126};
127
128struct as10x_tune_args {
129 /* frequency */
130 uint32_t freq;
131 /* bandwidth */
132 uint8_t bandwidth;
133 /* hierarchy selection */
134 uint8_t hier_select;
135 /* constellation */
136 uint8_t constellation;
137 /* hierarchy */
138 uint8_t hierarchy;
139 /* interleaving mode */
140 uint8_t interleaving_mode;
141 /* code rate */
142 uint8_t code_rate;
143 /* guard interval */
144 uint8_t guard_interval;
145 /* transmission mode */
146 uint8_t transmission_mode;
147};
148
149struct as10x_tune_status {
150 /* tune status */
151 uint8_t tune_state;
152 /* signal strength */
153 int16_t signal_strength;
154 /* packet error rate 10^-4 */
155 uint16_t PER;
156 /* bit error rate 10^-4 */
157 uint16_t BER;
158};
159
160struct as10x_demod_stats {
161 /* frame counter */
162 uint32_t frame_count;
163 /* Bad frame counter */
164 uint32_t bad_frame_count;
165 /* Number of wrong bytes fixed by Reed-Solomon */
166 uint32_t bytes_fixed_by_rs;
167 /* Averaged MER */
168 uint16_t mer;
169 /* statistics calculation state indicator (started or not) */
170 uint8_t has_started;
171};
172
173struct as10x_ts_filter {
174 uint16_t pid; /** valid PID value 0x00 : 0x2000 */
175 uint8_t type; /** Red TS_PID_TYPE_<N> values */
176 uint8_t idx; /** index in filtering table */
177};
178
179struct as10x_register_value {
180 uint8_t mode;
181 union {
182 uint8_t value8; /* 8 bit value */
183 uint16_t value16; /* 16 bit value */
184 uint32_t value32; /* 32 bit value */
185 }u;
186};
187
188#pragma pack()
189
190struct as10x_register_addr {
191 /* register addr */
192 uint32_t addr;
193 /* register mode access */
194 uint8_t mode;
195};
196
197
198#endif