Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / usb / dvb-usb / gp8psk.c
1 /* DVB USB compliant Linux driver for the
2  *  - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
3  *
4  * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
5  * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
6  *
7  * Thanks to GENPIX for the sample code used to implement this module.
8  *
9  * This module is based off the vp7045 and vp702x modules
10  *
11  *      This program is free software; you can redistribute it and/or modify it
12  *      under the terms of the GNU General Public License as published by the Free
13  *      Software Foundation, version 2.
14  *
15  * see Documentation/dvb/README.dvb-usb for more information
16  */
17 #include "gp8psk.h"
18
19 /* debug */
20 static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
21 int dvb_usb_gp8psk_debug;
22 module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
23 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
24
25 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
26
27 static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
28 {
29         return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
30 }
31
32 static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers)
33 {
34         return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1));
35 }
36
37 static void gp8psk_info(struct dvb_usb_device *d)
38 {
39         u8 fpga_vers, fw_vers[6];
40
41         if (!gp8psk_get_fw_version(d, fw_vers))
42                 info("FW Version = %i.%02i.%i (0x%x)  Build %4i/%02i/%02i",
43                 fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers),
44                 2000 + fw_vers[5], fw_vers[4], fw_vers[3]);
45         else
46                 info("failed to get FW version");
47
48         if (!gp8psk_get_fpga_version(d, &fpga_vers))
49                 info("FPGA Version = %i", fpga_vers);
50         else
51                 info("failed to get FPGA version");
52 }
53
54 int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
55 {
56         int ret = 0,try = 0;
57
58         if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
59                 return ret;
60
61         while (ret >= 0 && ret != blen && try < 3) {
62                 ret = usb_control_msg(d->udev,
63                         usb_rcvctrlpipe(d->udev,0),
64                         req,
65                         USB_TYPE_VENDOR | USB_DIR_IN,
66                         value,index,b,blen,
67                         2000);
68                 deb_info("reading number %d (ret: %d)\n",try,ret);
69                 try++;
70         }
71
72         if (ret < 0 || ret != blen) {
73                 warn("usb in %d operation failed.", req);
74                 ret = -EIO;
75         } else
76                 ret = 0;
77
78         deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
79         debug_dump(b,blen,deb_xfer);
80
81         mutex_unlock(&d->usb_mutex);
82
83         return ret;
84 }
85
86 int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
87                              u16 index, u8 *b, int blen)
88 {
89         int ret;
90
91         deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
92         debug_dump(b,blen,deb_xfer);
93
94         if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
95                 return ret;
96
97         if (usb_control_msg(d->udev,
98                         usb_sndctrlpipe(d->udev,0),
99                         req,
100                         USB_TYPE_VENDOR | USB_DIR_OUT,
101                         value,index,b,blen,
102                         2000) != blen) {
103                 warn("usb out operation failed.");
104                 ret = -EIO;
105         } else
106                 ret = 0;
107         mutex_unlock(&d->usb_mutex);
108
109         return ret;
110 }
111
112 static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
113 {
114         int ret;
115         const struct firmware *fw = NULL;
116         const u8 *ptr;
117         u8 *buf;
118         if ((ret = request_firmware(&fw, bcm4500_firmware,
119                                         &d->udev->dev)) != 0) {
120                 err("did not find the bcm4500 firmware file. (%s) "
121                         "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
122                         bcm4500_firmware,ret);
123                 return ret;
124         }
125
126         ret = -EINVAL;
127
128         if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
129                 goto out_rel_fw;
130
131         info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
132
133         ptr = fw->data;
134         buf = kmalloc(64, GFP_KERNEL | GFP_DMA);
135         if (!buf) {
136                 ret = -ENOMEM;
137                 goto out_rel_fw;
138         }
139
140         while (ptr[0] != 0xff) {
141                 u16 buflen = ptr[0] + 4;
142                 if (ptr + buflen >= fw->data + fw->size) {
143                         err("failed to load bcm4500 firmware.");
144                         goto out_free;
145                 }
146                 memcpy(buf, ptr, buflen);
147                 if (dvb_usb_generic_write(d, buf, buflen)) {
148                         err("failed to load bcm4500 firmware.");
149                         goto out_free;
150                 }
151                 ptr += buflen;
152         }
153
154         ret = 0;
155
156 out_free:
157         kfree(buf);
158 out_rel_fw:
159         release_firmware(fw);
160
161         return ret;
162 }
163
164 static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
165 {
166         u8 status, buf;
167         int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
168
169         if (onoff) {
170                 gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
171                 if (! (status & bm8pskStarted)) {  /* started */
172                         if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
173                                 gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
174                         if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
175                                 return -EINVAL;
176                         gp8psk_info(d);
177                 }
178
179                 if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
180                         if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
181                                 if(gp8psk_load_bcm4500fw(d))
182                                         return -EINVAL;
183
184                 if (! (status & bmIntersilOn)) /* LNB Power */
185                         if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
186                                         &buf, 1))
187                                 return -EINVAL;
188
189                 /* Set DVB mode to 1 */
190                 if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
191                         if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
192                                 return -EINVAL;
193                 /* Abort possible TS (if previous tune crashed) */
194                 if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
195                         return -EINVAL;
196         } else {
197                 /* Turn off LNB power */
198                 if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
199                         return -EINVAL;
200                 /* Turn off 8psk power */
201                 if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
202                         return -EINVAL;
203                 if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
204                         gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
205         }
206         return 0;
207 }
208
209 int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
210 {
211         u8 buf;
212         int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
213         /* Turn off 8psk power */
214         if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
215                 return -EINVAL;
216         /* Turn On 8psk power */
217         if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
218                 return -EINVAL;
219         /* load BCM4500 firmware */
220         if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
221                 if (gp8psk_load_bcm4500fw(d))
222                         return -EINVAL;
223         return 0;
224 }
225
226 static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
227 {
228         return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0);
229 }
230
231 static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
232 {
233         adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
234         return 0;
235 }
236
237 static struct dvb_usb_device_properties gp8psk_properties;
238
239 static int gp8psk_usb_probe(struct usb_interface *intf,
240                 const struct usb_device_id *id)
241 {
242         int ret;
243         struct usb_device *udev = interface_to_usbdev(intf);
244         ret = dvb_usb_device_init(intf, &gp8psk_properties,
245                                   THIS_MODULE, NULL, adapter_nr);
246         if (ret == 0) {
247                 info("found Genpix USB device pID = %x (hex)",
248                         le16_to_cpu(udev->descriptor.idProduct));
249         }
250         return ret;
251 }
252
253 static struct usb_device_id gp8psk_usb_table [] = {
254             { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) },
255             { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
256             { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
257             { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
258             { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_2) },
259 /*          { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
260             { 0 },
261 };
262 MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
263
264 static struct dvb_usb_device_properties gp8psk_properties = {
265         .usb_ctrl = CYPRESS_FX2,
266         .firmware = "dvb-usb-gp8psk-01.fw",
267
268         .num_adapters = 1,
269         .adapter = {
270                 {
271                 .num_frontends = 1,
272                 .fe = {{
273                         .streaming_ctrl   = gp8psk_streaming_ctrl,
274                         .frontend_attach  = gp8psk_frontend_attach,
275                         /* parameter for the MPEG2-data transfer */
276                         .stream = {
277                                 .type = USB_BULK,
278                                 .count = 7,
279                                 .endpoint = 0x82,
280                                 .u = {
281                                         .bulk = {
282                                                 .buffersize = 8192,
283                                         }
284                                 }
285                         },
286                 }},
287                 }
288         },
289         .power_ctrl       = gp8psk_power_ctrl,
290
291         .generic_bulk_ctrl_endpoint = 0x01,
292
293         .num_device_descs = 4,
294         .devices = {
295                 { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
296                   .cold_ids = { &gp8psk_usb_table[0], NULL },
297                   .warm_ids = { &gp8psk_usb_table[1], NULL },
298                 },
299                 { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
300                   .cold_ids = { NULL },
301                   .warm_ids = { &gp8psk_usb_table[2], NULL },
302                 },
303                 { .name = "Genpix SkyWalker-1 DVB-S receiver",
304                   .cold_ids = { NULL },
305                   .warm_ids = { &gp8psk_usb_table[3], NULL },
306                 },
307                 { .name = "Genpix SkyWalker-2 DVB-S receiver",
308                   .cold_ids = { NULL },
309                   .warm_ids = { &gp8psk_usb_table[4], NULL },
310                 },
311                 { NULL },
312         }
313 };
314
315 /* usb specific object needed to register this driver with the usb subsystem */
316 static struct usb_driver gp8psk_usb_driver = {
317         .name           = "dvb_usb_gp8psk",
318         .probe          = gp8psk_usb_probe,
319         .disconnect = dvb_usb_device_exit,
320         .id_table       = gp8psk_usb_table,
321 };
322
323 module_usb_driver(gp8psk_usb_driver);
324
325 MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
326 MODULE_DESCRIPTION("Driver for Genpix DVB-S");
327 MODULE_VERSION("1.1");
328 MODULE_LICENSE("GPL");