xref: /linux/drivers/usb/misc/emi62.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
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
21 typedef 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 
51 static int emi62_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest);
52 static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
53 static int emi62_load_firmware (struct usb_device *dev);
54 static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
55 static void emi62_disconnect(struct usb_interface *intf);
56 static int __init emi62_init (void);
57 static void __exit emi62_exit (void);
58 
59 
60 /* thanks to drivers/usb/serial/keyspan_pda.c code */
61 static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
62 {
63 	int result;
64 	unsigned char *buffer =  kmalloc (length, GFP_KERNEL);
65 
66 	if (!buffer) {
67 		err("emi62: kmalloc(%d) failed.", length);
68 		return -ENOMEM;
69 	}
70 	memcpy (buffer, data, length);
71 	/* Note: usb_control_msg returns negative value on error or length of the
72 	 * 		 data that was written! */
73 	result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
74 	kfree (buffer);
75 	return result;
76 }
77 
78 /* thanks to drivers/usb/serial/keyspan_pda.c code */
79 static int emi62_set_reset (struct usb_device *dev, unsigned char reset_bit)
80 {
81 	int response;
82 	info("%s - %d", __FUNCTION__, reset_bit);
83 
84 	response = emi62_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
85 	if (response < 0) {
86 		err("emi62: set_reset (%d) failed", reset_bit);
87 	}
88 	return response;
89 }
90 
91 #define FW_LOAD_SIZE		1023
92 
93 static int emi62_load_firmware (struct usb_device *dev)
94 {
95 	int err;
96 	int i;
97 	int pos = 0;	/* Position in hex record */
98 	__u32 addr;	/* Address to write */
99 	__u8 *buf;
100 
101 	dev_dbg(&dev->dev, "load_firmware\n");
102 	buf = kmalloc(FW_LOAD_SIZE, GFP_KERNEL);
103 	if (!buf) {
104 		err( "%s - error loading firmware: error = %d", __FUNCTION__, -ENOMEM);
105 		err = -ENOMEM;
106 		goto wraperr;
107 	}
108 
109 	/* Assert reset (stop the CPU in the EMI) */
110 	err = emi62_set_reset(dev,1);
111 	if (err < 0) {
112 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
113 		goto wraperr;
114 	}
115 
116 	/* 1. We need to put the loader for the FPGA into the EZ-USB */
117 	for (i=0; g_emi62_loader[i].type == 0; i++) {
118 		err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
119 		if (err < 0) {
120 			err("%s - error loading firmware: error = %d", __FUNCTION__, err);
121 			goto wraperr;
122 		}
123 	}
124 
125 	/* De-assert reset (let the CPU run) */
126 	err = emi62_set_reset(dev,0);
127 	msleep(250);	/* let device settle */
128 
129 	/* 2. We upload the FPGA firmware into the EMI
130 	 * Note: collect up to 1023 (yes!) bytes and send them with
131 	 * a single request. This is _much_ faster! */
132 	do {
133 		i = 0;
134 		addr = g_emi62bs[pos].address;
135 
136 		/* intel hex records are terminated with type 0 element */
137 		while ((g_emi62bs[pos].type == 0) && (i + g_emi62bs[pos].length < FW_LOAD_SIZE)) {
138 			memcpy(buf + i, g_emi62bs[pos].data, g_emi62bs[pos].length);
139 			i += g_emi62bs[pos].length;
140 			pos++;
141 		}
142 		err = emi62_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
143 		if (err < 0) {
144 			err("%s - error loading firmware: error = %d", __FUNCTION__, err);
145 			goto wraperr;
146 		}
147 	} while (i > 0);
148 
149 	/* Assert reset (stop the CPU in the EMI) */
150 	err = emi62_set_reset(dev,1);
151 	if (err < 0) {
152 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
153 		goto wraperr;
154 	}
155 
156 	/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
157 	for (i=0; g_emi62_loader[i].type == 0; i++) {
158 		err = emi62_writememory(dev, g_emi62_loader[i].address, g_emi62_loader[i].data, g_emi62_loader[i].length, ANCHOR_LOAD_INTERNAL);
159 		if (err < 0) {
160 			err("%s - error loading firmware: error = %d", __FUNCTION__, err);
161 			goto wraperr;
162 		}
163 	}
164 
165 	/* De-assert reset (let the CPU run) */
166 	err = emi62_set_reset(dev,0);
167 	if (err < 0) {
168 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
169 		goto wraperr;
170 	}
171 	msleep(250);	/* let device settle */
172 
173 	/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
174 
175 /* FIXME: quick and dirty ifdefs */
176 #ifdef SPDIF
177 	for (i=0; g_HexSpdifFw62[i].type == 0; i++) {
178 		if (!INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
179 			err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_EXTERNAL);
180 			if (err < 0) {
181 				err("%s - error loading firmware: error = %d", __FUNCTION__, err);
182 				goto wraperr;
183 			}
184 		}
185 	}
186 #else /* MIDI */
187 	for (i=0; g_HexMidiFw62[i].type == 0; i++) {
188 		if (!INTERNAL_RAM(g_HexMidiFw62[i].address)) {
189 			err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_EXTERNAL);
190 			if (err < 0) {
191 				err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
192 				goto wraperr;
193 				return err;
194 			}
195 		}
196 	}
197 #endif
198 	/* Assert reset (stop the CPU in the EMI) */
199 	err = emi62_set_reset(dev,1);
200 	if (err < 0) {
201 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
202 		goto wraperr;
203 	}
204 
205 /* FIXME: quick and dirty ifdefs */
206 #ifdef SPDIF
207 	for (i=0; g_HexSpdifFw62[i].type == 0; i++) {
208 		if (INTERNAL_RAM(g_HexSpdifFw62[i].address)) {
209 			err = emi62_writememory(dev, g_HexSpdifFw62[i].address, g_HexSpdifFw62[i].data, g_HexSpdifFw62[i].length, ANCHOR_LOAD_INTERNAL);
210 			if (err < 0) {
211 				err("%s - error loading firmware: error = %d", __FUNCTION__, err);
212 				goto wraperr;
213 			}
214 		}
215 	}
216 #else /* MIDI */
217 	for (i=0; g_HexMidiFw62[i].type == 0; i++) {
218 		if (INTERNAL_RAM(g_HexMidiFw62[i].address)) {
219 			err = emi62_writememory(dev, g_HexMidiFw62[i].address, g_HexMidiFw62[i].data, g_HexMidiFw62[i].length, ANCHOR_LOAD_INTERNAL);
220 			if (err < 0) {
221 				err("%s - error loading firmware: error = %d\n", __FUNCTION__, err);
222 				goto wraperr;
223 			}
224 		}
225 	}
226 #endif
227 
228 	/* De-assert reset (let the CPU run) */
229 	err = emi62_set_reset(dev,0);
230 	if (err < 0) {
231 		err("%s - error loading firmware: error = %d", __FUNCTION__, err);
232 		goto wraperr;
233 	}
234 	msleep(250);	/* let device settle */
235 
236 	kfree(buf);
237 
238 	/* return 1 to fail the driver inialization
239 	 * and give real driver change to load */
240 	return 1;
241 
242 wraperr:
243 	kfree(buf);
244 	dev_err(&dev->dev, "Error\n");
245 	return err;
246 }
247 
248 static __devinitdata struct usb_device_id id_table [] = {
249 	{ USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },
250 	{ }                                             /* Terminating entry */
251 };
252 
253 MODULE_DEVICE_TABLE (usb, id_table);
254 
255 static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id)
256 {
257 	struct usb_device *dev = interface_to_usbdev(intf);
258 	dev_dbg(&intf->dev, "emi62_probe\n");
259 
260 	info("%s start", __FUNCTION__);
261 
262 	emi62_load_firmware(dev);
263 
264 	/* do not return the driver context, let real audio driver do that */
265 	return -EIO;
266 }
267 
268 static void emi62_disconnect(struct usb_interface *intf)
269 {
270 }
271 
272 static struct usb_driver emi62_driver = {
273 	.name		= "emi62 - firmware loader",
274 	.probe		= emi62_probe,
275 	.disconnect	= emi62_disconnect,
276 	.id_table	= id_table,
277 };
278 
279 static int __init emi62_init (void)
280 {
281 	int retval;
282 	retval = usb_register (&emi62_driver);
283 	if (retval)
284 		printk(KERN_ERR "adi-emi: registration failed\n");
285 	return retval;
286 }
287 
288 static void __exit emi62_exit (void)
289 {
290 	usb_deregister (&emi62_driver);
291 }
292 
293 module_init(emi62_init);
294 module_exit(emi62_exit);
295 
296 MODULE_AUTHOR("tapio laxstr�m");
297 MODULE_DESCRIPTION("Emagic EMI 6|2m firmware loader.");
298 MODULE_LICENSE("GPL");
299 
300 /* vi:ai:syntax=c:sw=8:ts=8:tw=80
301  */
302