linux/drivers/media/usb/dvb-usb/gp8psk.c
<<
>>
Prefs
   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
  27static 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
  54int 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
  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;
 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
 156out_free:
 157        kfree(buf);
 158out_rel_fw:
 159        release_firmware(fw);
 160
 161        return ret;
 162}
 163
 164static 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
 209int 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
 226static 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
 231static 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
 237static struct dvb_usb_device_properties gp8psk_properties;
 238
 239static 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
 253static 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};
 262MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
 263
 264static 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 */
 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
 323module_usb_driver(gp8psk_usb_driver);
 324
 325MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
 326MODULE_DESCRIPTION("Driver for Genpix DVB-S");
 327MODULE_VERSION("1.1");
 328MODULE_LICENSE("GPL");
 329