linux/drivers/media/dvb/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
  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
 109        while (ptr[0] != 0xff) {
 110                u16 buflen = ptr[0] + 4;
 111                if (ptr + buflen >= fw->data + fw->size) {
 112                        err("failed to load bcm4500 firmware.");
 113                        goto out_free;
 114                }
 115                memcpy(buf, ptr, buflen);
 116                if (dvb_usb_generic_write(d, buf, buflen)) {
 117                        err("failed to load bcm4500 firmware.");
 118                        goto out_free;
 119                }
 120                ptr += buflen;
 121        }
 122
 123        ret = 0;
 124
 125out_free:
 126        kfree(buf);
 127out_rel_fw:
 128        release_firmware(fw);
 129
 130        return ret;
 131}
 132
 133static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
 134{
 135        u8 status, buf;
 136        int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
 137
 138        if (onoff) {
 139                gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
 140                if (! (status & bm8pskStarted)) {  /* started */
 141                        if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
 142                                gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
 143                        if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
 144                                return -EINVAL;
 145                }
 146
 147                if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
 148                        if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
 149                                if(gp8psk_load_bcm4500fw(d))
 150                                        return -EINVAL;
 151
 152                if (! (status & bmIntersilOn)) /* LNB Power */
 153                        if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
 154                                        &buf, 1))
 155                                return -EINVAL;
 156
 157                /* Set DVB mode to 1 */
 158                if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
 159                        if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
 160                                return -EINVAL;
 161                /* Abort possible TS (if previous tune crashed) */
 162                if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
 163                        return -EINVAL;
 164        } else {
 165                /* Turn off LNB power */
 166                if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
 167                        return -EINVAL;
 168                /* Turn off 8psk power */
 169                if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
 170                        return -EINVAL;
 171                if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
 172                        gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
 173        }
 174        return 0;
 175}
 176
 177int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
 178{
 179        u8 buf;
 180        int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
 181        /* Turn off 8psk power */
 182        if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
 183                return -EINVAL;
 184        /* Turn On 8psk power */
 185        if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
 186                return -EINVAL;
 187        /* load BCM4500 firmware */
 188        if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
 189                if (gp8psk_load_bcm4500fw(d))
 190                        return -EINVAL;
 191        return 0;
 192}
 193
 194static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 195{
 196        return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0);
 197}
 198
 199static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
 200{
 201        adap->fe = gp8psk_fe_attach(adap->dev);
 202        return 0;
 203}
 204
 205static struct dvb_usb_device_properties gp8psk_properties;
 206
 207static int gp8psk_usb_probe(struct usb_interface *intf,
 208                const struct usb_device_id *id)
 209{
 210        int ret;
 211        struct usb_device *udev = interface_to_usbdev(intf);
 212        ret = dvb_usb_device_init(intf, &gp8psk_properties,
 213                                  THIS_MODULE, NULL, adapter_nr);
 214        if (ret == 0) {
 215                info("found Genpix USB device pID = %x (hex)",
 216                        le16_to_cpu(udev->descriptor.idProduct));
 217        }
 218        return ret;
 219}
 220
 221static struct usb_device_id gp8psk_usb_table [] = {
 222            { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) },
 223            { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
 224            { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
 225            { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
 226/*          { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
 227            { 0 },
 228};
 229MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
 230
 231static struct dvb_usb_device_properties gp8psk_properties = {
 232        .usb_ctrl = CYPRESS_FX2,
 233        .firmware = "dvb-usb-gp8psk-01.fw",
 234
 235        .num_adapters = 1,
 236        .adapter = {
 237                {
 238                        .streaming_ctrl   = gp8psk_streaming_ctrl,
 239                        .frontend_attach  = gp8psk_frontend_attach,
 240                        /* parameter for the MPEG2-data transfer */
 241                        .stream = {
 242                                .type = USB_BULK,
 243                                .count = 7,
 244                                .endpoint = 0x82,
 245                                .u = {
 246                                        .bulk = {
 247                                                .buffersize = 8192,
 248                                        }
 249                                }
 250                        },
 251                }
 252        },
 253        .power_ctrl       = gp8psk_power_ctrl,
 254
 255        .generic_bulk_ctrl_endpoint = 0x01,
 256
 257        .num_device_descs = 3,
 258        .devices = {
 259                { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
 260                  .cold_ids = { &gp8psk_usb_table[0], NULL },
 261                  .warm_ids = { &gp8psk_usb_table[1], NULL },
 262                },
 263                { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
 264                  .cold_ids = { NULL },
 265                  .warm_ids = { &gp8psk_usb_table[2], NULL },
 266                },
 267                { .name = "Genpix SkyWalker-1 DVB-S receiver",
 268                  .cold_ids = { NULL },
 269                  .warm_ids = { &gp8psk_usb_table[3], NULL },
 270                },
 271                { NULL },
 272        }
 273};
 274
 275/* usb specific object needed to register this driver with the usb subsystem */
 276static struct usb_driver gp8psk_usb_driver = {
 277        .name           = "dvb_usb_gp8psk",
 278        .probe          = gp8psk_usb_probe,
 279        .disconnect = dvb_usb_device_exit,
 280        .id_table       = gp8psk_usb_table,
 281};
 282
 283/* module stuff */
 284static int __init gp8psk_usb_module_init(void)
 285{
 286        int result;
 287        if ((result = usb_register(&gp8psk_usb_driver))) {
 288                err("usb_register failed. (%d)",result);
 289                return result;
 290        }
 291
 292        return 0;
 293}
 294
 295static void __exit gp8psk_usb_module_exit(void)
 296{
 297        /* deregister this driver from the USB subsystem */
 298        usb_deregister(&gp8psk_usb_driver);
 299}
 300
 301module_init(gp8psk_usb_module_init);
 302module_exit(gp8psk_usb_module_exit);
 303
 304MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
 305MODULE_DESCRIPTION("Driver for Genpix 8psk-to-USB2 DVB-S");
 306MODULE_VERSION("1.1");
 307MODULE_LICENSE("GPL");
 308