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 */ 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 25DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 26 27int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) 28{ 29 int ret = 0,try = 0; 30 31 if ((ret = mutex_lock_interruptible(&d->usb_mutex))) 32 return ret; 33 34 while (ret >= 0 && ret != blen && try < 3) { 35 ret = usb_control_msg(d->udev, 36 usb_rcvctrlpipe(d->udev,0), 37 req, 38 USB_TYPE_VENDOR | USB_DIR_IN, 39 value,index,b,blen, 40 2000); 41 deb_info("reading number %d (ret: %d)\n",try,ret); 42 try++; 43 } 44 45 if (ret < 0 || ret != blen) { 46 warn("usb in %d operation failed.", req); 47 ret = -EIO; 48 } else 49 ret = 0; 50 51 deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index); 52 debug_dump(b,blen,deb_xfer); 53 54 mutex_unlock(&d->usb_mutex); 55 56 return ret; 57} 58 59int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, 60 u16 index, u8 *b, int blen) 61{ 62 int ret; 63 64 deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); 65 debug_dump(b,blen,deb_xfer); 66 67 if ((ret = mutex_lock_interruptible(&d->usb_mutex))) 68 return ret; 69 70 if (usb_control_msg(d->udev, 71 usb_sndctrlpipe(d->udev,0), 72 req, 73 USB_TYPE_VENDOR | USB_DIR_OUT, 74 value,index,b,blen, 75 2000) != blen) { 76 warn("usb out operation failed."); 77 ret = -EIO; 78 } else 79 ret = 0; 80 mutex_unlock(&d->usb_mutex); 81 82 return ret; 83} 84 85static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) 86{ 87 int ret; 88 const struct firmware *fw = NULL; 89 const u8 *ptr; 90 u8 *buf; 91 if ((ret = request_firmware(&fw, bcm4500_firmware, 92 &d->udev->dev)) != 0) { 93 err("did not find the bcm4500 firmware file. (%s) " 94 "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", 95 bcm4500_firmware,ret); 96 return ret; 97 } 98 99 ret = -EINVAL; 100 101 if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) 102 goto out_rel_fw; 103 104 info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware); 105 106 ptr = fw->data; 107 buf = kmalloc(64, GFP_KERNEL | GFP_DMA); 108 if (!buf) { 109 ret = -ENOMEM; 110 goto out_rel_fw; 111 } 112 113 while (ptr[0] != 0xff) { 114 u16 buflen = ptr[0] + 4; 115 if (ptr + buflen >= fw->data + fw->size) { 116 err("failed to load bcm4500 firmware."); 117 goto out_free; 118 } 119 memcpy(buf, ptr, buflen); 120 if (dvb_usb_generic_write(d, buf, buflen)) { 121 err("failed to load bcm4500 firmware."); 122 goto out_free; 123 } 124 ptr += buflen; 125 } 126 127 ret = 0; 128 129out_free: 130 kfree(buf); 131out_rel_fw: 132 release_firmware(fw); 133 134 return ret; 135} 136 137static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) 138{ 139 u8 status, buf; 140 int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); 141 142 if (onoff) { 143 gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); 144 if (! (status & bm8pskStarted)) { /* started */ 145 if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) 146 gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0); 147 if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) 148 return -EINVAL; 149 } 150 151 if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) 152 if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */ 153 if(gp8psk_load_bcm4500fw(d)) 154 return -EINVAL; 155 156 if (! (status & bmIntersilOn)) /* LNB Power */ 157 if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, 158 &buf, 1)) 159 return -EINVAL; 160 161 /* Set DVB mode to 1 */ 162 if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) 163 if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) 164 return -EINVAL; 165 /* Abort possible TS (if previous tune crashed) */ 166 if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0)) 167 return -EINVAL; 168 } else { 169 /* Turn off LNB power */ 170 if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) 171 return -EINVAL; 172 /* Turn off 8psk power */ 173 if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) 174 return -EINVAL; 175 if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) 176 gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0); 177 } 178 return 0; 179} 180 181int gp8psk_bcm4500_reload(struct dvb_usb_device *d) 182{ 183 u8 buf; 184 int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); 185 /* Turn off 8psk power */ 186 if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) 187 return -EINVAL; 188 /* Turn On 8psk power */ 189 if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) 190 return -EINVAL; 191 /* load BCM4500 firmware */ 192 if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) 193 if (gp8psk_load_bcm4500fw(d)) 194 return -EINVAL; 195 return 0; 196} 197 198static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) 199{ 200 return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0); 201} 202 203static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap) 204{ 205 adap->fe = gp8psk_fe_attach(adap->dev); 206 return 0; 207} 208 209static struct dvb_usb_device_properties gp8psk_properties; 210 211static int gp8psk_usb_probe(struct usb_interface *intf, 212 const struct usb_device_id *id) 213{ 214 int ret; 215 struct usb_device *udev = interface_to_usbdev(intf); 216 ret = dvb_usb_device_init(intf, &gp8psk_properties, 217 THIS_MODULE, NULL, adapter_nr); 218 if (ret == 0) { 219 info("found Genpix USB device pID = %x (hex)", 220 le16_to_cpu(udev->descriptor.idProduct)); 221 } 222 return ret; 223} 224 225static struct usb_device_id gp8psk_usb_table [] = { 226 { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) }, 227 { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, 228 { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, 229 { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, 230/* { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */ 231 { 0 }, 232}; 233MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); 234 235static struct dvb_usb_device_properties gp8psk_properties = { 236 .usb_ctrl = CYPRESS_FX2, 237 .firmware = "dvb-usb-gp8psk-01.fw", 238 239 .num_adapters = 1, 240 .adapter = { 241 { 242 .streaming_ctrl = gp8psk_streaming_ctrl, 243 .frontend_attach = gp8psk_frontend_attach, 244 /* parameter for the MPEG2-data transfer */ 245 .stream = { 246 .type = USB_BULK, 247 .count = 7, 248 .endpoint = 0x82, 249 .u = { 250 .bulk = { 251 .buffersize = 8192, 252 } 253 } 254 }, 255 } 256 }, 257 .power_ctrl = gp8psk_power_ctrl, 258 259 .generic_bulk_ctrl_endpoint = 0x01, 260 261 .num_device_descs = 3, 262 .devices = { 263 { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", 264 .cold_ids = { &gp8psk_usb_table[0], NULL }, 265 .warm_ids = { &gp8psk_usb_table[1], NULL }, 266 }, 267 { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver", 268 .cold_ids = { NULL }, 269 .warm_ids = { &gp8psk_usb_table[2], NULL }, 270 }, 271 { .name = "Genpix SkyWalker-1 DVB-S receiver", 272 .cold_ids = { NULL }, 273 .warm_ids = { &gp8psk_usb_table[3], NULL }, 274 }, 275 { NULL }, 276 } 277}; 278 279/* usb specific object needed to register this driver with the usb subsystem */ 280static struct usb_driver gp8psk_usb_driver = { 281 .name = "dvb_usb_gp8psk", 282 .probe = gp8psk_usb_probe, 283 .disconnect = dvb_usb_device_exit, 284 .id_table = gp8psk_usb_table, 285}; 286 287/* module stuff */ 288static int __init gp8psk_usb_module_init(void) 289{ 290 int result; 291 if ((result = usb_register(&gp8psk_usb_driver))) { 292 err("usb_register failed. (%d)",result); 293 return result; 294 } 295 296 return 0; 297} 298 299static void __exit gp8psk_usb_module_exit(void) 300{ 301 /* deregister this driver from the USB subsystem */ 302 usb_deregister(&gp8psk_usb_driver); 303} 304 305module_init(gp8psk_usb_module_init); 306module_exit(gp8psk_usb_module_exit); 307 308MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); 309MODULE_DESCRIPTION("Driver for Genpix 8psk-to-USB2 DVB-S"); 310MODULE_VERSION("1.1"); 311MODULE_LICENSE("GPL"); 312