diff options
author | Eliot Blennerhassett <eblennerhassett@audioscience.com> | 2011-07-21 23:52:42 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-07-22 01:49:23 -0400 |
commit | 95a4c6e785bf7e2e5cde7f92c9252877b4fcea46 (patch) | |
tree | 9215aad12e57eca88581390571630c29a1a3fcbc /sound/pci/asihpi/hpidspcd.c | |
parent | 58fbf77ff5d258a15a4084940e08219d7ee6f449 (diff) |
ALSA: asihpi - DSP code loader API now independent of OS
The loader API has been revised so that OS specific data is kept
local to hpidspcd.c, and the public API is unchanged across OSes.
Signed-off-by: Eliot Blennerhassett <eblennerhassett@audioscience.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/asihpi/hpidspcd.c')
-rw-r--r-- | sound/pci/asihpi/hpidspcd.c | 135 |
1 files changed, 54 insertions, 81 deletions
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c index 5c6ea113d219..987538819b24 100644 --- a/sound/pci/asihpi/hpidspcd.c +++ b/sound/pci/asihpi/hpidspcd.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /***********************************************************************/ | 1 | /***********************************************************************/ |
2 | /*! | 2 | /** |
3 | 3 | ||
4 | AudioScience HPI driver | 4 | AudioScience HPI driver |
5 | Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> | 5 | Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of version 2 of the GNU General Public License as | 8 | it under the terms of version 2 of the GNU General Public License as |
@@ -18,90 +18,60 @@ | |||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | 19 | ||
20 | \file | 20 | \file |
21 | Functions for reading DSP code to load into DSP | 21 | Functions for reading DSP code using |
22 | |||
23 | (Linux only:) If DSPCODE_FIRMWARE_LOADER is defined, code is read using | ||
24 | hotplug firmware loader from individual dsp code files | 22 | hotplug firmware loader from individual dsp code files |
25 | 23 | */ | |
26 | If neither of the above is defined, code is read from linked arrays. | ||
27 | DSPCODE_ARRAY is defined. | ||
28 | |||
29 | HPI_INCLUDE_**** must be defined | ||
30 | and the appropriate hzz?????.c or hex?????.c linked in | ||
31 | |||
32 | */ | ||
33 | /***********************************************************************/ | 24 | /***********************************************************************/ |
34 | #define SOURCEFILE_NAME "hpidspcd.c" | 25 | #define SOURCEFILE_NAME "hpidspcd.c" |
35 | #include "hpidspcd.h" | 26 | #include "hpidspcd.h" |
36 | #include "hpidebug.h" | 27 | #include "hpidebug.h" |
37 | 28 | ||
38 | /** | 29 | struct dsp_code_private { |
39 | Header structure for binary dsp code file (see asidsp.doc) | 30 | /** Firmware descriptor */ |
40 | This structure must match that used in s2bin.c for generation of asidsp.bin | 31 | const struct firmware *firmware; |
41 | */ | 32 | struct pci_dev *dev; |
42 | |||
43 | #ifndef DISABLE_PRAGMA_PACK1 | ||
44 | #pragma pack(push, 1) | ||
45 | #endif | ||
46 | |||
47 | struct code_header { | ||
48 | u32 size; | ||
49 | char type[4]; | ||
50 | u32 adapter; | ||
51 | u32 version; | ||
52 | u32 crc; | ||
53 | }; | 33 | }; |
54 | 34 | ||
55 | #ifndef DISABLE_PRAGMA_PACK1 | ||
56 | #pragma pack(pop) | ||
57 | #endif | ||
58 | |||
59 | #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \ | 35 | #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \ |
60 | HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER))) | 36 | HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER))) |
61 | 37 | ||
62 | /***********************************************************************/ | ||
63 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
64 | /*-------------------------------------------------------------------*/ | 39 | /*-------------------------------------------------------------------*/ |
65 | short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code, | 40 | short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, |
66 | u32 *pos_error_code) | 41 | u32 *os_error_code) |
67 | { | 42 | { |
68 | const struct firmware *ps_firmware = ps_dsp_code->ps_firmware; | 43 | const struct firmware *firmware; |
44 | struct pci_dev *dev = os_data; | ||
69 | struct code_header header; | 45 | struct code_header header; |
70 | char fw_name[20]; | 46 | char fw_name[20]; |
71 | int err; | 47 | int err; |
72 | 48 | ||
73 | sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); | 49 | sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); |
74 | 50 | ||
75 | err = request_firmware(&ps_firmware, fw_name, | 51 | err = request_firmware(&firmware, fw_name, &dev->dev); |
76 | &ps_dsp_code->ps_dev->dev); | ||
77 | 52 | ||
78 | if (err != 0) { | 53 | if (err || !firmware) { |
79 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 54 | dev_printk(KERN_ERR, &dev->dev, |
80 | "%d, request_firmware failed for %s\n", err, | 55 | "%d, request_firmware failed for %s\n", err, |
81 | fw_name); | 56 | fw_name); |
82 | goto error1; | 57 | goto error1; |
83 | } | 58 | } |
84 | if (ps_firmware->size < sizeof(header)) { | 59 | if (firmware->size < sizeof(header)) { |
85 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 60 | dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n", |
86 | "Header size too small %s\n", fw_name); | 61 | fw_name); |
87 | goto error2; | ||
88 | } | ||
89 | memcpy(&header, ps_firmware->data, sizeof(header)); | ||
90 | if (header.adapter != adapter) { | ||
91 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | ||
92 | "Adapter type incorrect %4x != %4x\n", header.adapter, | ||
93 | adapter); | ||
94 | goto error2; | 62 | goto error2; |
95 | } | 63 | } |
96 | if (header.size != ps_firmware->size) { | 64 | memcpy(&header, firmware->data, sizeof(header)); |
97 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 65 | |
98 | "Code size wrong %d != %ld\n", header.size, | 66 | if ((header.type != 0x45444F43) || /* "CODE" */ |
99 | (unsigned long)ps_firmware->size); | 67 | (header.adapter != adapter) |
68 | || (header.size != firmware->size)) { | ||
69 | dev_printk(KERN_ERR, &dev->dev, "Invalid firmware file\n"); | ||
100 | goto error2; | 70 | goto error2; |
101 | } | 71 | } |
102 | 72 | ||
103 | if (header.version / 100 != HPI_VER_DECIMAL / 100) { | 73 | if ((header.version / 100 & ~1) != (HPI_VER_DECIMAL / 100 & ~1)) { |
104 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, | 74 | dev_printk(KERN_ERR, &dev->dev, |
105 | "Incompatible firmware version " | 75 | "Incompatible firmware version " |
106 | "DSP image %d != Driver %d\n", header.version, | 76 | "DSP image %d != Driver %d\n", header.version, |
107 | HPI_VER_DECIMAL); | 77 | HPI_VER_DECIMAL); |
@@ -109,67 +79,70 @@ short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code, | |||
109 | } | 79 | } |
110 | 80 | ||
111 | if (header.version != HPI_VER_DECIMAL) { | 81 | if (header.version != HPI_VER_DECIMAL) { |
112 | dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev, | 82 | dev_printk(KERN_WARNING, &dev->dev, |
113 | "Firmware: release version mismatch DSP image %d != Driver %d\n", | 83 | "Firmware: release version mismatch DSP image %d != Driver %d\n", |
114 | header.version, HPI_VER_DECIMAL); | 84 | header.version, HPI_VER_DECIMAL); |
115 | } | 85 | } |
116 | 86 | ||
117 | HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); | 87 | HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); |
118 | ps_dsp_code->ps_firmware = ps_firmware; | 88 | dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL); |
119 | ps_dsp_code->block_length = header.size / sizeof(u32); | 89 | if (!dsp_code->pvt) |
120 | ps_dsp_code->word_count = sizeof(header) / sizeof(u32); | 90 | return HPI_ERROR_MEMORY_ALLOC; |
121 | ps_dsp_code->version = header.version; | 91 | |
122 | ps_dsp_code->crc = header.crc; | 92 | dsp_code->pvt->dev = dev; |
93 | dsp_code->pvt->firmware = firmware; | ||
94 | dsp_code->header = header; | ||
95 | dsp_code->block_length = header.size / sizeof(u32); | ||
96 | dsp_code->word_count = sizeof(header) / sizeof(u32); | ||
123 | return 0; | 97 | return 0; |
124 | 98 | ||
125 | error2: | 99 | error2: |
126 | release_firmware(ps_firmware); | 100 | release_firmware(firmware); |
127 | error1: | 101 | error1: |
128 | ps_dsp_code->ps_firmware = NULL; | 102 | dsp_code->block_length = 0; |
129 | ps_dsp_code->block_length = 0; | ||
130 | return HPI_ERROR_DSP_FILE_NOT_FOUND; | 103 | return HPI_ERROR_DSP_FILE_NOT_FOUND; |
131 | } | 104 | } |
132 | 105 | ||
133 | /*-------------------------------------------------------------------*/ | 106 | /*-------------------------------------------------------------------*/ |
134 | void hpi_dsp_code_close(struct dsp_code *ps_dsp_code) | 107 | void hpi_dsp_code_close(struct dsp_code *dsp_code) |
135 | { | 108 | { |
136 | if (ps_dsp_code->ps_firmware != NULL) { | 109 | if (dsp_code->pvt->firmware) { |
137 | HPI_DEBUG_LOG(DEBUG, "dsp code closed\n"); | 110 | HPI_DEBUG_LOG(DEBUG, "dsp code closed\n"); |
138 | release_firmware(ps_dsp_code->ps_firmware); | 111 | release_firmware(dsp_code->pvt->firmware); |
139 | ps_dsp_code->ps_firmware = NULL; | 112 | dsp_code->pvt->firmware = NULL; |
140 | } | 113 | } |
114 | kfree(dsp_code->pvt); | ||
141 | } | 115 | } |
142 | 116 | ||
143 | /*-------------------------------------------------------------------*/ | 117 | /*-------------------------------------------------------------------*/ |
144 | void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code) | 118 | void hpi_dsp_code_rewind(struct dsp_code *dsp_code) |
145 | { | 119 | { |
146 | /* Go back to start of data, after header */ | 120 | /* Go back to start of data, after header */ |
147 | ps_dsp_code->word_count = sizeof(struct code_header) / sizeof(u32); | 121 | dsp_code->word_count = sizeof(struct code_header) / sizeof(u32); |
148 | } | 122 | } |
149 | 123 | ||
150 | /*-------------------------------------------------------------------*/ | 124 | /*-------------------------------------------------------------------*/ |
151 | short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword) | 125 | short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword) |
152 | { | 126 | { |
153 | if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length) | 127 | if (dsp_code->word_count + 1 > dsp_code->block_length) |
154 | return HPI_ERROR_DSP_FILE_FORMAT; | 128 | return HPI_ERROR_DSP_FILE_FORMAT; |
155 | 129 | ||
156 | *pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code-> | 130 | *pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code-> |
157 | word_count]; | 131 | word_count]; |
158 | ps_dsp_code->word_count++; | 132 | dsp_code->word_count++; |
159 | return 0; | 133 | return 0; |
160 | } | 134 | } |
161 | 135 | ||
162 | /*-------------------------------------------------------------------*/ | 136 | /*-------------------------------------------------------------------*/ |
163 | short hpi_dsp_code_read_block(size_t words_requested, | 137 | short hpi_dsp_code_read_block(size_t words_requested, |
164 | struct dsp_code *ps_dsp_code, u32 **ppblock) | 138 | struct dsp_code *dsp_code, u32 **ppblock) |
165 | { | 139 | { |
166 | if (ps_dsp_code->word_count + words_requested > | 140 | if (dsp_code->word_count + words_requested > dsp_code->block_length) |
167 | ps_dsp_code->block_length) | ||
168 | return HPI_ERROR_DSP_FILE_FORMAT; | 141 | return HPI_ERROR_DSP_FILE_FORMAT; |
169 | 142 | ||
170 | *ppblock = | 143 | *ppblock = |
171 | ((u32 *)(ps_dsp_code->ps_firmware->data)) + | 144 | ((u32 *)(dsp_code->pvt->firmware->data)) + |
172 | ps_dsp_code->word_count; | 145 | dsp_code->word_count; |
173 | ps_dsp_code->word_count += words_requested; | 146 | dsp_code->word_count += words_requested; |
174 | return 0; | 147 | return 0; |
175 | } | 148 | } |