emi26.c 8.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/* 
 * Emagic EMI 2|6 usb audio interface firmware loader.
 * Copyright (C) 2002
4
 * 	Tapio Laxström (tapio.laxstrom@iptime.fi)
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, as published by
 * the Free Software Foundation, version 2.
 * 
 * emi26.c,v 1.13 2002/03/08 13:10:26 tapio Exp
 */
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
18
#include <linux/delay.h>
D
David Woodhouse 已提交
19 20
#include <linux/firmware.h>
#include <linux/ihex.h>
L
Linus Torvalds 已提交
21 22 23 24 25 26 27 28 29 30 31 32

#define EMI26_VENDOR_ID 		0x086a  /* Emagic Soft-und Hardware GmBH */
#define EMI26_PRODUCT_ID		0x0100	/* EMI 2|6 without firmware */
#define EMI26B_PRODUCT_ID		0x0102	/* EMI 2|6 without firmware */

#define ANCHOR_LOAD_INTERNAL	0xA0	/* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
#define ANCHOR_LOAD_EXTERNAL	0xA3	/* This command is not implemented in the core. Requires firmware */
#define ANCHOR_LOAD_FPGA	0xA5	/* This command is not implemented in the core. Requires firmware. Emagic extension */
#define MAX_INTERNAL_ADDRESS	0x1B3F	/* This is the highest internal RAM address for the AN2131Q */
#define CPUCS_REG		0x7F92  /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */ 
#define INTERNAL_RAM(address)   (address <= MAX_INTERNAL_ADDRESS)

D
David Woodhouse 已提交
33 34 35
static int emi26_writememory( struct usb_device *dev, int address,
			      const unsigned char *data, int length,
			      __u8 bRequest);
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43 44
static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
static int emi26_load_firmware (struct usb_device *dev);
static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi26_disconnect(struct usb_interface *intf);
static int __init emi26_init (void);
static void __exit emi26_exit (void);


/* thanks to drivers/usb/serial/keyspan_pda.c code */
D
David Woodhouse 已提交
45 46 47
static int emi26_writememory (struct usb_device *dev, int address,
			      const unsigned char *data, int length,
			      __u8 request)
L
Linus Torvalds 已提交
48 49
{
	int result;
50
	unsigned char *buffer =  kmemdup(data, length, GFP_KERNEL);
L
Linus Torvalds 已提交
51 52

	if (!buffer) {
53
		dev_err(&dev->dev, "kmalloc(%d) failed.\n", length);
L
Linus Torvalds 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66
		return -ENOMEM;
	}
	/* Note: usb_control_msg returns negative value on error or length of the
	 * 		 data that was written! */
	result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
	kfree (buffer);
	return result;
}

/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit)
{
	int response;
67
	dev_info(&dev->dev, "%s - %d\n", __func__, reset_bit);
68
	/* printk(KERN_DEBUG "%s - %d", __func__, reset_bit); */
L
Linus Torvalds 已提交
69 70
	response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
	if (response < 0) {
71
		dev_err(&dev->dev, "set_reset (%d) failed\n", reset_bit);
L
Linus Torvalds 已提交
72 73 74 75 76 77 78 79
	}
	return response;
}

#define FW_LOAD_SIZE		1023

static int emi26_load_firmware (struct usb_device *dev)
{
D
David Woodhouse 已提交
80 81 82 83
	const struct firmware *loader_fw = NULL;
	const struct firmware *bitstream_fw = NULL;
	const struct firmware *firmware_fw = NULL;
	const struct ihex_binrec *rec;
L
Linus Torvalds 已提交
84 85 86 87 88 89 90
	int err;
	int i;
	__u32 addr;	/* Address to write */
	__u8 *buf;

	buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
	if (!buf) {
91 92
		dev_err(&dev->dev, "%s - error loading firmware: error = %d\n",
			__func__, -ENOMEM);
L
Linus Torvalds 已提交
93 94 95 96
		err = -ENOMEM;
		goto wraperr;
	}

D
David Woodhouse 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109
	err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev);
	if (err)
		goto nofw;

	err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw",
				    &dev->dev);
	if (err)
		goto nofw;

	err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw",
				    &dev->dev);
	if (err) {
	nofw:
110 111
		dev_err(&dev->dev, "%s - request_firmware() failed\n",
			__func__);
D
David Woodhouse 已提交
112 113 114
		goto wraperr;
	}

L
Linus Torvalds 已提交
115 116 117
	/* Assert reset (stop the CPU in the EMI) */
	err = emi26_set_reset(dev,1);
	if (err < 0) {
118 119
		dev_err(&dev->dev,"%s - error loading firmware: error = %d\n",
			__func__, err);
L
Linus Torvalds 已提交
120 121 122
		goto wraperr;
	}

D
David Woodhouse 已提交
123
	rec = (const struct ihex_binrec *)loader_fw->data;
L
Linus Torvalds 已提交
124
	/* 1. We need to put the loader for the FPGA into the EZ-USB */
D
David Woodhouse 已提交
125 126 127 128
	while (rec) {
		err = emi26_writememory(dev, be32_to_cpu(rec->addr),
					rec->data, be16_to_cpu(rec->len),
					ANCHOR_LOAD_INTERNAL);
L
Linus Torvalds 已提交
129
		if (err < 0) {
130
			err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
131 132
			goto wraperr;
		}
D
David Woodhouse 已提交
133
		rec = ihex_next_binrec(rec);
L
Linus Torvalds 已提交
134 135 136 137
	}

	/* De-assert reset (let the CPU run) */
	err = emi26_set_reset(dev,0);
O
Oliver Neukum 已提交
138
	if (err < 0) {
139
		err("%s - error loading firmware: error = %d", __func__, err);
O
Oliver Neukum 已提交
140 141
		goto wraperr;
	}
142
	msleep(250);	/* let device settle */
L
Linus Torvalds 已提交
143 144 145 146

	/* 2. We upload the FPGA firmware into the EMI
	 * Note: collect up to 1023 (yes!) bytes and send them with
	 * a single request. This is _much_ faster! */
D
David Woodhouse 已提交
147
	rec = (const struct ihex_binrec *)bitstream_fw->data;
L
Linus Torvalds 已提交
148 149
	do {
		i = 0;
D
David Woodhouse 已提交
150
		addr = be32_to_cpu(rec->addr);
L
Linus Torvalds 已提交
151 152

		/* intel hex records are terminated with type 0 element */
D
David Woodhouse 已提交
153 154 155 156
		while (rec && (i + be16_to_cpu(rec->len) < FW_LOAD_SIZE)) {
			memcpy(buf + i, rec->data, be16_to_cpu(rec->len));
			i += be16_to_cpu(rec->len);
			rec = ihex_next_binrec(rec);
L
Linus Torvalds 已提交
157 158 159
		}
		err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
		if (err < 0) {
160
			err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
161 162
			goto wraperr;
		}
M
Marcin Slusarz 已提交
163
	} while (rec);
L
Linus Torvalds 已提交
164 165 166 167

	/* Assert reset (stop the CPU in the EMI) */
	err = emi26_set_reset(dev,1);
	if (err < 0) {
168
		err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
169 170 171 172
		goto wraperr;
	}

	/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
D
David Woodhouse 已提交
173 174 175 176 177
	for (rec = (const struct ihex_binrec *)loader_fw->data;
	     rec; rec = ihex_next_binrec(rec)) {
		err = emi26_writememory(dev, be32_to_cpu(rec->addr),
					rec->data, be16_to_cpu(rec->len),
					ANCHOR_LOAD_INTERNAL);
L
Linus Torvalds 已提交
178
		if (err < 0) {
179
			err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
180 181 182
			goto wraperr;
		}
	}
183
	msleep(250);	/* let device settle */
L
Linus Torvalds 已提交
184 185 186 187

	/* De-assert reset (let the CPU run) */
	err = emi26_set_reset(dev,0);
	if (err < 0) {
188
		err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
189 190 191 192
		goto wraperr;
	}

	/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
D
David Woodhouse 已提交
193 194 195 196 197 198 199

	for (rec = (const struct ihex_binrec *)firmware_fw->data;
	     rec; rec = ihex_next_binrec(rec)) {
		if (!INTERNAL_RAM(be32_to_cpu(rec->addr))) {
			err = emi26_writememory(dev, be32_to_cpu(rec->addr),
						rec->data, be16_to_cpu(rec->len),
						ANCHOR_LOAD_EXTERNAL);
L
Linus Torvalds 已提交
200
			if (err < 0) {
201
				err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
202 203 204 205 206 207 208 209
				goto wraperr;
			}
		}
	}
	
	/* Assert reset (stop the CPU in the EMI) */
	err = emi26_set_reset(dev,1);
	if (err < 0) {
210
		err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
211 212 213
		goto wraperr;
	}

D
David Woodhouse 已提交
214 215 216 217 218 219
	for (rec = (const struct ihex_binrec *)firmware_fw->data;
	     rec; rec = ihex_next_binrec(rec)) {
		if (INTERNAL_RAM(be32_to_cpu(rec->addr))) {
			err = emi26_writememory(dev, be32_to_cpu(rec->addr),
						rec->data, be16_to_cpu(rec->len),
						ANCHOR_LOAD_INTERNAL);
L
Linus Torvalds 已提交
220
			if (err < 0) {
221
				err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
222 223 224 225 226 227 228 229
				goto wraperr;
			}
		}
	}

	/* De-assert reset (let the CPU run) */
	err = emi26_set_reset(dev,0);
	if (err < 0) {
230
		err("%s - error loading firmware: error = %d", __func__, err);
L
Linus Torvalds 已提交
231 232
		goto wraperr;
	}
233
	msleep(250);	/* let device settle */
L
Linus Torvalds 已提交
234 235 236 237 238 239

	/* return 1 to fail the driver inialization
	 * and give real driver change to load */
	err = 1;

wraperr:
D
David Woodhouse 已提交
240 241 242 243
	release_firmware(loader_fw);
	release_firmware(bitstream_fw);
	release_firmware(firmware_fw);

L
Linus Torvalds 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
	kfree(buf);
	return err;
}

static struct usb_device_id id_table [] = {
	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) },
	{ }                                             /* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, id_table);

static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);

260
	dev_info(&intf->dev, "%s start\n", __func__);
L
Linus Torvalds 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291

	emi26_load_firmware(dev);

	/* do not return the driver context, let real audio driver do that */
	return -EIO;
}

static void emi26_disconnect(struct usb_interface *intf)
{
}

static struct usb_driver emi26_driver = {
	.name		= "emi26 - firmware loader",
	.probe		= emi26_probe,
	.disconnect	= emi26_disconnect,
	.id_table	= id_table,
};

static int __init emi26_init (void)
{
	return usb_register(&emi26_driver);
}

static void __exit emi26_exit (void)
{
	usb_deregister (&emi26_driver);
}

module_init(emi26_init);
module_exit(emi26_exit);

292
MODULE_AUTHOR("Tapio Laxström");
L
Linus Torvalds 已提交
293 294 295
MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader.");
MODULE_LICENSE("GPL");

D
David Woodhouse 已提交
296 297 298
MODULE_FIRMWARE("emi26/loader.fw");
MODULE_FIRMWARE("emi26/bitstream.fw");
MODULE_FIRMWARE("emi26/firmware.fw");
L
Linus Torvalds 已提交
299 300
/* vi:ai:syntax=c:sw=8:ts=8:tw=80
 */