- patches.arch/x86_mce_intel_decode_physical_address.patch:
[linux-flexiantxendom0-3.2.10.git] / sound / pci / asihpi / hpidspcd.c
1 /***********************************************************************/
2 /*!
3
4     AudioScience HPI driver
5     Copyright (C) 1997-2010  AudioScience Inc. <support@audioscience.com>
6
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
9     published by the Free Software Foundation;
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 \file
21 Functions for reading DSP code to load into DSP
22
23 (Linux only:) If DSPCODE_FIRMWARE_LOADER is defined, code is read using
24 hotplug firmware loader from individual dsp code files
25
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 /***********************************************************************/
34 #define SOURCEFILE_NAME "hpidspcd.c"
35 #include "hpidspcd.h"
36 #include "hpidebug.h"
37
38 /**
39  Header structure for binary dsp code file (see asidsp.doc)
40  This structure must match that used in s2bin.c for generation of asidsp.bin
41  */
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 };
54
55 #ifndef DISABLE_PRAGMA_PACK1
56 #pragma pack(pop)
57 #endif
58
59 #define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
60             HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
61
62 /***********************************************************************/
63 #include "linux/pci.h"
64 /*-------------------------------------------------------------------*/
65 short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
66         u32 *pos_error_code)
67 {
68         const struct firmware *ps_firmware = ps_dsp_code->ps_firmware;
69         struct code_header header;
70         char fw_name[20];
71         int err;
72
73         sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
74         HPI_DEBUG_LOG(INFO, "requesting firmware for %s\n", fw_name);
75
76         err = request_firmware(&ps_firmware, fw_name,
77                 &ps_dsp_code->ps_dev->dev);
78         if (err != 0) {
79                 HPI_DEBUG_LOG(ERROR, "%d, request_firmware failed for  %s\n",
80                         err, fw_name);
81                 goto error1;
82         }
83         if (ps_firmware->size < sizeof(header)) {
84                 HPI_DEBUG_LOG(ERROR, "header size too small %s\n", fw_name);
85                 goto error2;
86         }
87         memcpy(&header, ps_firmware->data, sizeof(header));
88         if (header.adapter != adapter) {
89                 HPI_DEBUG_LOG(ERROR, "adapter type incorrect %4x != %4x\n",
90                         header.adapter, adapter);
91                 goto error2;
92         }
93         if (header.size != ps_firmware->size) {
94                 HPI_DEBUG_LOG(ERROR, "code size wrong  %d != %ld\n",
95                         header.size, (unsigned long)ps_firmware->size);
96                 goto error2;
97         }
98
99         if (header.version / 10000 != HPI_VER_DECIMAL / 10000) {
100                 HPI_DEBUG_LOG(ERROR,
101                         "firmware major version mismatch "
102                         "DSP image %d != driver %d\n", header.version,
103                         HPI_VER_DECIMAL);
104                 goto error2;
105         }
106
107         if (header.version != HPI_VER_DECIMAL) {
108                 HPI_DEBUG_LOG(WARNING,
109                         "version mismatch  DSP image %d != driver %d\n",
110                         header.version, HPI_VER_DECIMAL);
111                 /* goto error2;  still allow driver to load */
112         }
113
114         HPI_DEBUG_LOG(INFO, "dsp code %s opened\n", fw_name);
115         ps_dsp_code->ps_firmware = ps_firmware;
116         ps_dsp_code->block_length = header.size / sizeof(u32);
117         ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
118         ps_dsp_code->version = header.version;
119         ps_dsp_code->crc = header.crc;
120         return 0;
121
122 error2:
123         release_firmware(ps_firmware);
124 error1:
125         ps_dsp_code->ps_firmware = NULL;
126         ps_dsp_code->block_length = 0;
127         return HPI_ERROR_DSP_FILE_NOT_FOUND;
128 }
129
130 /*-------------------------------------------------------------------*/
131 void hpi_dsp_code_close(struct dsp_code *ps_dsp_code)
132 {
133         if (ps_dsp_code->ps_firmware != NULL) {
134                 HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
135                 release_firmware(ps_dsp_code->ps_firmware);
136                 ps_dsp_code->ps_firmware = NULL;
137         }
138 }
139
140 /*-------------------------------------------------------------------*/
141 void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code)
142 {
143         /* Go back to start of  data, after header */
144         ps_dsp_code->word_count = sizeof(struct code_header) / sizeof(u32);
145 }
146
147 /*-------------------------------------------------------------------*/
148 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword)
149 {
150         if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length)
151                 return (HPI_ERROR_DSP_FILE_FORMAT);
152
153         *pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code->
154                 word_count];
155         ps_dsp_code->word_count++;
156         return 0;
157 }
158
159 /*-------------------------------------------------------------------*/
160 short hpi_dsp_code_read_block(size_t words_requested,
161         struct dsp_code *ps_dsp_code, u32 **ppblock)
162 {
163         if (ps_dsp_code->word_count + words_requested >
164                 ps_dsp_code->block_length)
165                 return HPI_ERROR_DSP_FILE_FORMAT;
166
167         *ppblock =
168                 ((u32 *)(ps_dsp_code->ps_firmware->data)) +
169                 ps_dsp_code->word_count;
170         ps_dsp_code->word_count += words_requested;
171         return 0;
172 }