blob: 5d0384dd45b5ed1ed2e638acdddf9fe86ea2e628 [file] [log] [blame]
Alan Nisota9bbe0762006-05-14 13:23:56 -03001/* DVB USB compliant Linux driver for the
Alan Nisota458b6342007-08-18 17:52:35 -03002 * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
Alan Nisota9bbe0762006-05-14 13:23:56 -03003 *
Alan Nisota458b6342007-08-18 17:52:35 -03004 * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
5 * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
Alan Nisota9bbe0762006-05-14 13:23:56 -03006 *
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 */
20static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
21int dvb_usb_gp8psk_debug;
22module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
23MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
24
Janne Grunau78e92002008-04-09 19:13:13 -030025DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
26
VDR User9e21cca2010-10-30 15:49:49 -030027static 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
32static 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
37static 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
Alan Nisota9bbe0762006-05-14 13:23:56 -030054int 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) {
Alan Nisota458b6342007-08-18 17:52:35 -030073 warn("usb in %d operation failed.", req);
Alan Nisota9bbe0762006-05-14 13:23:56 -030074 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
86int 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
112static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
113{
114 int ret;
115 const struct firmware *fw = NULL;
David Woodhouse3a9282c2008-05-24 00:13:08 +0100116 const u8 *ptr;
117 u8 *buf;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300118 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
Patrick Boettcher976e3482006-05-14 13:29:48 -0300126 ret = -EINVAL;
127
128 if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
129 goto out_rel_fw;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300130
Alan Nisota458b6342007-08-18 17:52:35 -0300131 info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
Alan Nisota9bbe0762006-05-14 13:23:56 -0300132
133 ptr = fw->data;
Alan Nisota458b6342007-08-18 17:52:35 -0300134 buf = kmalloc(64, GFP_KERNEL | GFP_DMA);
Jiri Slaby205161e2010-04-27 18:11:20 -0300135 if (!buf) {
136 ret = -ENOMEM;
137 goto out_rel_fw;
138 }
Alan Nisota9bbe0762006-05-14 13:23:56 -0300139
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.");
Patrick Boettcher976e3482006-05-14 13:29:48 -0300144 goto out_free;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300145 }
146 memcpy(buf, ptr, buflen);
147 if (dvb_usb_generic_write(d, buf, buflen)) {
148 err("failed to load bcm4500 firmware.");
Patrick Boettcher976e3482006-05-14 13:29:48 -0300149 goto out_free;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300150 }
151 ptr += buflen;
152 }
Patrick Boettcher976e3482006-05-14 13:29:48 -0300153
154 ret = 0;
155
156out_free:
Alan Nisota9bbe0762006-05-14 13:23:56 -0300157 kfree(buf);
Patrick Boettcher976e3482006-05-14 13:29:48 -0300158out_rel_fw:
159 release_firmware(fw);
160
161 return ret;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300162}
163
164static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
165{
166 u8 status, buf;
Alan Nisota458b6342007-08-18 17:52:35 -0300167 int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
168
Alan Nisota9bbe0762006-05-14 13:23:56 -0300169 if (onoff) {
170 gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
Alan Nisota458b6342007-08-18 17:52:35 -0300171 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);
Alan Nisota9bbe0762006-05-14 13:23:56 -0300174 if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
175 return -EINVAL;
VDR User9e21cca2010-10-30 15:49:49 -0300176 gp8psk_info(d);
Alan Nisota458b6342007-08-18 17:52:35 -0300177 }
Alan Nisota9bbe0762006-05-14 13:23:56 -0300178
Alan Nisota458b6342007-08-18 17:52:35 -0300179 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))
Marcin Slusarz7fa7b852008-05-11 19:53:39 -0300182 return -EINVAL;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300183
Alan Nisota458b6342007-08-18 17:52:35 -0300184 if (! (status & bmIntersilOn)) /* LNB Power */
Alan Nisota9bbe0762006-05-14 13:23:56 -0300185 if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
186 &buf, 1))
Marcin Slusarz7fa7b852008-05-11 19:53:39 -0300187 return -EINVAL;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300188
Alan Nisota458b6342007-08-18 17:52:35 -0300189 /* 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))
Marcin Slusarz7fa7b852008-05-11 19:53:39 -0300192 return -EINVAL;
Alan Nisota458b6342007-08-18 17:52:35 -0300193 /* Abort possible TS (if previous tune crashed) */
194 if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
Marcin Slusarz7fa7b852008-05-11 19:53:39 -0300195 return -EINVAL;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300196 } else {
197 /* Turn off LNB power */
198 if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
Marcin Slusarz7fa7b852008-05-11 19:53:39 -0300199 return -EINVAL;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300200 /* Turn off 8psk power */
201 if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
202 return -EINVAL;
Alan Nisota458b6342007-08-18 17:52:35 -0300203 if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
204 gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
Alan Nisota9bbe0762006-05-14 13:23:56 -0300205 }
206 return 0;
207}
208
Alan Nisota02ebf232008-12-20 12:03:06 -0300209int 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))
Hans Verkuilda1b5c92008-12-30 07:07:53 -0300222 return -EINVAL;
Alan Nisota02ebf232008-12-20 12:03:06 -0300223 return 0;
224}
Alan Nisota9bbe0762006-05-14 13:23:56 -0300225
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300226static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
Alan Nisota9bbe0762006-05-14 13:23:56 -0300227{
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300228 return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0);
Alan Nisota9bbe0762006-05-14 13:23:56 -0300229}
230
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300231static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
Alan Nisota9bbe0762006-05-14 13:23:56 -0300232{
Michael Krufky77eed212011-09-06 09:31:57 -0300233 adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
Alan Nisota9bbe0762006-05-14 13:23:56 -0300234 return 0;
235}
236
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300237static struct dvb_usb_device_properties gp8psk_properties;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300238
239static int gp8psk_usb_probe(struct usb_interface *intf,
240 const struct usb_device_id *id)
241{
Alan Nisota458b6342007-08-18 17:52:35 -0300242 int ret;
243 struct usb_device *udev = interface_to_usbdev(intf);
Janne Grunau78e92002008-04-09 19:13:13 -0300244 ret = dvb_usb_device_init(intf, &gp8psk_properties,
245 THIS_MODULE, NULL, adapter_nr);
Alan Nisota458b6342007-08-18 17:52:35 -0300246 if (ret == 0) {
247 info("found Genpix USB device pID = %x (hex)",
248 le16_to_cpu(udev->descriptor.idProduct));
249 }
250 return ret;
Alan Nisota9bbe0762006-05-14 13:23:56 -0300251}
252
253static struct usb_device_id gp8psk_usb_table [] = {
Alan Nisota458b6342007-08-18 17:52:35 -0300254 { 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) },
Derek Kellybdd17512010-10-16 14:23:51 -0300258 { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_2) },
Alan Nisota86cf5f82009-05-20 05:52:13 -0300259/* { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
Alan Nisota9bbe0762006-05-14 13:23:56 -0300260 { 0 },
261};
262MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
263
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300264static struct dvb_usb_device_properties gp8psk_properties = {
Alan Nisota9bbe0762006-05-14 13:23:56 -0300265 .usb_ctrl = CYPRESS_FX2,
266 .firmware = "dvb-usb-gp8psk-01.fw",
267
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300268 .num_adapters = 1,
269 .adapter = {
270 {
Michael Krufky77eed212011-09-06 09:31:57 -0300271 .num_frontends = 1,
272 .fe = {{
Patrick Boettcher01451e72006-10-13 11:34:46 -0300273 .streaming_ctrl = gp8psk_streaming_ctrl,
274 .frontend_attach = gp8psk_frontend_attach,
275 /* parameter for the MPEG2-data transfer */
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300276 .stream = {
277 .type = USB_BULK,
Patrick Boettcher01451e72006-10-13 11:34:46 -0300278 .count = 7,
279 .endpoint = 0x82,
280 .u = {
281 .bulk = {
282 .buffersize = 8192,
283 }
284 }
285 },
Michael Krufky77eed212011-09-06 09:31:57 -0300286 }},
Patrick Boettcher4d43e132006-09-30 06:53:48 -0300287 }
288 },
289 .power_ctrl = gp8psk_power_ctrl,
290
291 .generic_bulk_ctrl_endpoint = 0x01,
Alan Nisota9bbe0762006-05-14 13:23:56 -0300292
Derek Kellybdd17512010-10-16 14:23:51 -0300293 .num_device_descs = 4,
Alan Nisota9bbe0762006-05-14 13:23:56 -0300294 .devices = {
Alan Nisota458b6342007-08-18 17:52:35 -0300295 { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
Alan Nisota9bbe0762006-05-14 13:23:56 -0300296 .cold_ids = { &gp8psk_usb_table[0], NULL },
297 .warm_ids = { &gp8psk_usb_table[1], NULL },
298 },
Alan Nisota458b6342007-08-18 17:52:35 -0300299 { .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 },
Derek Kellybdd17512010-10-16 14:23:51 -0300307 { .name = "Genpix SkyWalker-2 DVB-S receiver",
308 .cold_ids = { NULL },
309 .warm_ids = { &gp8psk_usb_table[4], NULL },
310 },
Randy Dunlapab9caf92006-09-28 14:03:26 -0300311 { NULL },
Alan Nisota9bbe0762006-05-14 13:23:56 -0300312 }
313};
314
315/* usb specific object needed to register this driver with the usb subsystem */
316static 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
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800323module_usb_driver(gp8psk_usb_driver);
Alan Nisota9bbe0762006-05-14 13:23:56 -0300324
325MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
Derek Kellyd12da8e2010-10-16 16:18:15 -0300326MODULE_DESCRIPTION("Driver for Genpix DVB-S");
Alan Nisota458b6342007-08-18 17:52:35 -0300327MODULE_VERSION("1.1");
Alan Nisota9bbe0762006-05-14 13:23:56 -0300328MODULE_LICENSE("GPL");