linux/drivers/usb/misc/emi62.c
<<
>>
Prefs
   1/* 
   2 * Emagic EMI 2|6 usb audio interface firmware loader.
   3 * Copyright (C) 2002
   4 *      Tapio Laxström (tapio.laxstrom@iptime.fi)
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License, as published by
   8 * the Free Software Foundation, version 2.
   9 * 
  10 * $Id: emi62.c,v 1.15 2002/04/23 06:13:59 tapio Exp $
  11 */
  12#include <linux/kernel.h>
  13#include <linux/errno.h>
  14#include <linux/slab.h>
  15#include <linux/init.h>
  16#include <linux/module.h>
  17#include <linux/usb.h>
  18#include <linux/delay.h>
  19
  20#define MAX_INTEL_HEX_RECORD_LENGTH 16
  21typedef struct _INTEL_HEX_RECORD
  22{
  23        __u32   length;
  24        __u32   address;
  25        __u32   type;
  26        __u8    data[MAX_INTEL_HEX_RECORD_LENGTH];
  27} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
  28
  29/* include firmware (variables)*/
  30
  31/* FIXME: This is quick and dirty solution! */
  32#define SPDIF   /* if you want SPDIF comment next line */
  33//#undef SPDIF  /* if you want MIDI uncomment this line */ 
  34
  35#ifdef SPDIF
  36#  include "emi62_fw_s.h" /* spdif fw */
  37#else
  38#  include "emi62_fw_m.h" /* midi fw */
  39#endif
  40
  41#define EMI62_VENDOR_ID                 0x086a  /* Emagic Soft-und Hardware GmBH */
  42#define EMI62_PRODUCT_ID                0x0110  /* EMI 6|2m without firmware */
  43
  44#define ANCHOR_LOAD_INTERNAL    0xA0    /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
  45#define ANCHOR_LOAD_EXTERNAL    0xA3    /* This command is not implemented in the core. Requires firmware */
  46#define ANCHOR_LOAD_FPGA        0xA5    /* This command is not implemented in the core. Requires firmware. Emagic extension */
  47#define MAX_INTERNAL_ADDRESS    0x1B3F  /* This is the highest internal RAM address for the AN2131Q */
  48#define CPUCS_REG               0x7F92  /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */ 
  49#define INTERNAL_RAM(address)   (address <= MAX_INTERNAL_ADDRESS)
  50
  51static int emi62_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest);
  52static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
  53static int emi62_load_firmware (struct usb_device *dev);
  54static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
  55static void emi62_disconnect(struct usb_interface *intf);
  56static int __init emi62_init (void);
  57static void __exit emi62_exit (void);
  58
  59
  60/* thanks to drivers/usb/serial/keyspan_pda.c code */
  61static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
  62{
  63        int result;
  64        unsigned char *buffer =  kmemdup(data, length, GFP_KERNEL);
  65
  66        if (!buffer) {
  67                err("emi62: kmalloc(%d) failed.", length);
  68                return -ENOMEM;
  69        }
  70        /* Note: usb_control_msg returns negative value on error or length of the
  71         *               data that was written! */
  72        result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
  73        kfree (buffer);
  74        return result;
  75}
  76
  77/* thanks to drivers/usb/serial/keyspan_pda.c code */
  78static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
  79{
  80        int response;
  81        info("%s - %d", __FUNCTION__, reset_bit);
  82        
  83        response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
  84        if (response < 0) {
  85                err("emi62: set_reset (%d) failed", reset_bit);
  86        }
  87        return response;
  88}
  89
  90#define FW_LOAD_SIZE            1023
  91
  92static int emi62_load_firmware (struct usb_device *dev)
  93{
  94        int err;
  95        int i;
  96        int pos = 0;    /* Position in hex record */
  97        __u32 addr;     /* Address to write */
  98        __u8 *buf;
  99
 100        dev_dbg(&dev->dev, "load_firmware\n");
 101        buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
 102        if (!buf) {
 103                err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM);
 104                err = -ENOMEM;
 105                goto wraperr;
 106        }
 107
 108        /* Assert reset (stop the CPU in the EMI) */
 109        err = emi62_set_reset(dev,1);
 110        if (err < 0) {
 111                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 112                goto wraperr;
 113        }
 114
 115        /* 1. We need to put the loader for the FPGA into the EZ-USB */
 116        for (i=0; g_emi62_loader[i].type == 0; i++) {
 117                err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
 118                if (err < 0) {
 119                        err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 120                        goto wraperr;
 121                }
 122        }
 123
 124        /* De-assert reset (let the CPU run) */
 125        err = emi62_set_reset(dev,0);
 126        if (err < 0) {
 127                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 128                goto wraperr;
 129        }
 130        msleep(250);    /* let device settle */
 131
 132        /* 2. We upload the FPGA firmware into the EMI
 133         * Note: collect up to 1023 (yes!) bytes and send them with
 134         * a single request. This is _much_ faster! */
 135        do {
 136                i = 0;
 137                addr = g_emi62bs[pos].address;
 138
 139                /* intel hex records are terminated with type 0 element */
 140                while ((g_emi62bs[pos].type == 0) && (i + g_emi62bs[pos].length < FW_LOAD_SIZE)) {
 141                        memcpy(buf + i, g_emi62bs[pos].data, g_emi62bs[pos].length);
 142                        i += g_emi62bs[pos].length;
 143                        pos++;
 144                }
 145                err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
 146                if (err < 0) {
 147                        err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 148                        goto wraperr;
 149                }
 150        } while (i > 0);
 151
 152        /* Assert reset (stop the CPU in the EMI) */
 153        err = emi62_set_reset(dev,1);
 154        if (err < 0) {
 155                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 156                goto wraperr;
 157        }
 158
 159        /* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
 160        for (i=0; g_emi62_loader[i].type == 0; i++) {
 161                err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
 162                if (err < 0) {
 163                        err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 164                        goto wraperr;
 165                }
 166        }
 167
 168        /* De-assert reset (let the CPU run) */
 169        err = emi62_set_reset(dev,0);
 170        if (err < 0) {
 171                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 172                goto wraperr;
 173        }
 174        msleep(250);    /* let device settle */
 175
 176        /* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
 177
 178/* FIXME: quick and dirty ifdefs */
 179#ifdef SPDIF
 180        for (i=0; g_HexSpdifFw62[i].type == 0; i++) {
 181                if (!INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
 182                        err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_EXTERNAL);
 183                        if (err < 0) {
 184                                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 185                                goto wraperr;
 186                        }
 187                }
 188        }
 189#else /* MIDI */
 190        for (i=0; g_HexMidiFw62[i].type == 0; i++) {
 191                if (!INTERNAL_RAM(g_HexMidiFw62[i].address)) {
 192                        err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_EXTERNAL);
 193                        if (err < 0) {
 194                                err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
 195                                goto wraperr;
 196                                return err;
 197                        }
 198                }
 199        }
 200#endif  
 201        /* Assert reset (stop the CPU in the EMI) */
 202        err = emi62_set_reset(dev,1);
 203        if (err < 0) {
 204                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 205                goto wraperr;
 206        }
 207
 208/* FIXME: quick and dirty ifdefs */
 209#ifdef SPDIF
 210        for (i=0; g_HexSpdifFw62[i].type == 0; i++) {
 211                if (INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
 212                        err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_INTERNAL);
 213                        if (err < 0) {
 214                                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 215                                goto wraperr;
 216                        }
 217                }
 218        }
 219#else /* MIDI */
 220        for (i=0; g_HexMidiFw62[i].type == 0; i++) {
 221                if (INTERNAL_RAM(g_HexMidiFw62[i].address)) {
 222                        err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_INTERNAL);
 223                        if (err < 0) {
 224                                err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
 225                                goto wraperr;
 226                        }
 227                }
 228        }
 229#endif
 230        
 231        /* De-assert reset (let the CPU run) */
 232        err = emi62_set_reset(dev,0);
 233        if (err < 0) {
 234                err("%s - error loading firmware: error = %d", __FUNCTION__, err);
 235                goto wraperr;
 236        }
 237        msleep(250);    /* let device settle */
 238
 239        kfree(buf);
 240
 241        /* return 1 to fail the driver inialization
 242         * and give real driver change to load */
 243        return 1;
 244
 245wraperr:
 246        kfree(buf);
 247        dev_err(&dev->dev, "Error\n");
 248        return err;
 249}
 250
 251static __devinitdata struct usb_device_id id_table [] = {
 252        { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },
 253        { }                                             /* Terminating entry */
 254};
 255
 256MODULE_DEVICE_TABLE (usb, id_table);
 257
 258static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id)
 259{
 260        struct usb_device *dev = interface_to_usbdev(intf);
 261        dev_dbg(&intf->dev, "emi62_probe\n");
 262
 263        info("%s start", __FUNCTION__); 
 264
 265        emi62_load_firmware(dev);
 266
 267        /* do not return the driver context, let real audio driver do that */
 268        return -EIO;
 269}
 270
 271static void emi62_disconnect(struct usb_interface *intf)
 272{
 273}
 274
 275static struct usb_driver emi62_driver = {
 276        .name           = "emi62 - firmware loader",
 277        .probe          = emi62_probe,
 278        .disconnect     = emi62_disconnect,
 279        .id_table       = id_table,
 280};
 281
 282static int __init emi62_init (void)
 283{
 284        int retval;
 285        retval = usb_register (&emi62_driver);
 286        if (retval)
 287                printk(KERN_ERR "adi-emi: registration failed\n");
 288        return retval;
 289}
 290
 291static void __exit emi62_exit (void)
 292{
 293        usb_deregister (&emi62_driver);
 294}
 295
 296module_init(emi62_init);
 297module_exit(emi62_exit);
 298
 299MODULE_AUTHOR("Tapio Laxström");
 300MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader.");
 301MODULE_LICENSE("GPL");
 302
 303/* vi:ai:syntax=c:sw=8:ts=8:tw=80
 304 */
 305