Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/asihpi/hpidspcd.c
10817 views
1
/***********************************************************************/
2
/*!
3
4
AudioScience HPI driver
5
Copyright (C) 1997-2010 AudioScience Inc. <[email protected]>
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
75
err = request_firmware(&ps_firmware, fw_name,
76
&ps_dsp_code->ps_dev->dev);
77
78
if (err != 0) {
79
dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
80
"%d, request_firmware failed for %s\n", err,
81
fw_name);
82
goto error1;
83
}
84
if (ps_firmware->size < sizeof(header)) {
85
dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
86
"Header size too small %s\n", 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;
95
}
96
if (header.size != ps_firmware->size) {
97
dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
98
"Code size wrong %d != %ld\n", header.size,
99
(unsigned long)ps_firmware->size);
100
goto error2;
101
}
102
103
if (header.version / 100 != HPI_VER_DECIMAL / 100) {
104
dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
105
"Incompatible firmware version "
106
"DSP image %d != Driver %d\n", header.version,
107
HPI_VER_DECIMAL);
108
goto error2;
109
}
110
111
if (header.version != HPI_VER_DECIMAL) {
112
dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev,
113
"Firmware: release version mismatch DSP image %d != Driver %d\n",
114
header.version, HPI_VER_DECIMAL);
115
}
116
117
HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
118
ps_dsp_code->ps_firmware = ps_firmware;
119
ps_dsp_code->block_length = header.size / sizeof(u32);
120
ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
121
ps_dsp_code->version = header.version;
122
ps_dsp_code->crc = header.crc;
123
return 0;
124
125
error2:
126
release_firmware(ps_firmware);
127
error1:
128
ps_dsp_code->ps_firmware = NULL;
129
ps_dsp_code->block_length = 0;
130
return HPI_ERROR_DSP_FILE_NOT_FOUND;
131
}
132
133
/*-------------------------------------------------------------------*/
134
void hpi_dsp_code_close(struct dsp_code *ps_dsp_code)
135
{
136
if (ps_dsp_code->ps_firmware != NULL) {
137
HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
138
release_firmware(ps_dsp_code->ps_firmware);
139
ps_dsp_code->ps_firmware = NULL;
140
}
141
}
142
143
/*-------------------------------------------------------------------*/
144
void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code)
145
{
146
/* Go back to start of data, after header */
147
ps_dsp_code->word_count = sizeof(struct code_header) / sizeof(u32);
148
}
149
150
/*-------------------------------------------------------------------*/
151
short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword)
152
{
153
if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length)
154
return HPI_ERROR_DSP_FILE_FORMAT;
155
156
*pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code->
157
word_count];
158
ps_dsp_code->word_count++;
159
return 0;
160
}
161
162
/*-------------------------------------------------------------------*/
163
short hpi_dsp_code_read_block(size_t words_requested,
164
struct dsp_code *ps_dsp_code, u32 **ppblock)
165
{
166
if (ps_dsp_code->word_count + words_requested >
167
ps_dsp_code->block_length)
168
return HPI_ERROR_DSP_FILE_FORMAT;
169
170
*ppblock =
171
((u32 *)(ps_dsp_code->ps_firmware->data)) +
172
ps_dsp_code->word_count;
173
ps_dsp_code->word_count += words_requested;
174
return 0;
175
}
176
177