aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/asihpi/hpidspcd.c
diff options
context:
space:
mode:
authorEliot Blennerhassett <eblennerhassett@audioscience.com>2011-07-21 23:52:42 -0400
committerTakashi Iwai <tiwai@suse.de>2011-07-22 01:49:23 -0400
commit95a4c6e785bf7e2e5cde7f92c9252877b4fcea46 (patch)
tree9215aad12e57eca88581390571630c29a1a3fcbc /sound/pci/asihpi/hpidspcd.c
parent58fbf77ff5d258a15a4084940e08219d7ee6f449 (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.c135
1 files changed, 54 insertions, 81 deletions
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
index 5c6ea113d21..987538819b2 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
21Functions for reading DSP code to load into DSP 21Functions for reading DSP code using
22
23(Linux only:) If DSPCODE_FIRMWARE_LOADER is defined, code is read using
24hotplug firmware loader from individual dsp code files 22hotplug firmware loader from individual dsp code files
25 23*/
26If neither of the above is defined, code is read from linked arrays.
27DSPCODE_ARRAY is defined.
28
29HPI_INCLUDE_**** must be defined
30and 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/** 29struct 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
47struct 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/*-------------------------------------------------------------------*/
65short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code, 40short 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
125error2: 99error2:
126 release_firmware(ps_firmware); 100 release_firmware(firmware);
127error1: 101error1:
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/*-------------------------------------------------------------------*/
134void hpi_dsp_code_close(struct dsp_code *ps_dsp_code) 107void 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/*-------------------------------------------------------------------*/
144void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code) 118void 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/*-------------------------------------------------------------------*/
151short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword) 125short 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/*-------------------------------------------------------------------*/
163short hpi_dsp_code_read_block(size_t words_requested, 137short 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}