aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEliot Blennerhassett <eblennerhassett@audioscience.com>2010-04-21 12:17:39 -0400
committerTakashi Iwai <tiwai@suse.de>2010-04-22 01:21:53 -0400
commit719f82d3987aad4cc9f46d19c35f362672545cad (patch)
tree3f9edf749da5e5d11bfa82336db99a01dd489979
parentcf0dbba515415bb19b11f9323d5f7bebd7f24fd6 (diff)
ALSA: Add support of AudioScience ASI boards
Added the support of AudioScience ASI boards. The driver has been tested for years on alsa-driver external tree, now finally got merged to the kernel. Signed-off-by: Eliot Blennerhassett <eblennerhassett@audioscience.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt10
-rw-r--r--sound/pci/Kconfig12
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/asihpi/Makefile5
-rw-r--r--sound/pci/asihpi/asihpi.c3002
-rw-r--r--sound/pci/asihpi/hpi.h2001
-rw-r--r--sound/pci/asihpi/hpi6000.c1841
-rw-r--r--sound/pci/asihpi/hpi6000.h70
-rw-r--r--sound/pci/asihpi/hpi6205.c2332
-rw-r--r--sound/pci/asihpi/hpi6205.h93
-rw-r--r--sound/pci/asihpi/hpi_internal.h1641
-rw-r--r--sound/pci/asihpi/hpicmn.c643
-rw-r--r--sound/pci/asihpi/hpicmn.h64
-rw-r--r--sound/pci/asihpi/hpidebug.c225
-rw-r--r--sound/pci/asihpi/hpidebug.h385
-rw-r--r--sound/pci/asihpi/hpidspcd.c172
-rw-r--r--sound/pci/asihpi/hpidspcd.h104
-rw-r--r--sound/pci/asihpi/hpifunc.c3864
-rw-r--r--sound/pci/asihpi/hpimsginit.c130
-rw-r--r--sound/pci/asihpi/hpimsginit.h40
-rw-r--r--sound/pci/asihpi/hpimsgx.c907
-rw-r--r--sound/pci/asihpi/hpimsgx.h36
-rw-r--r--sound/pci/asihpi/hpioctl.c484
-rw-r--r--sound/pci/asihpi/hpioctl.h38
-rw-r--r--sound/pci/asihpi/hpios.c114
-rw-r--r--sound/pci/asihpi/hpios.h178
-rw-r--r--sound/pci/asihpi/hpipcida.h37
27 files changed, 18429 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index bfcbbf88c44d..dc681badca67 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -227,6 +227,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
227 227
228 The power-management is supported. 228 The power-management is supported.
229 229
230 Module snd-asihpi
231 -----------------
232
233 Module for AudioScience ASI soundcards
234
235 enable_hpi_hwdep - enable HPI hwdep for AudioScience soundcard
236
237 This module supports multiple cards.
238 The driver requires the firmware loader support on kernel.
239
230 Module snd-atiixp 240 Module snd-atiixp
231 ----------------- 241 -----------------
232 242
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1298c68d6bf0..517ae65ffc8e 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -58,6 +58,18 @@ config SND_ALI5451
58 To compile this driver as a module, choose M here: the module 58 To compile this driver as a module, choose M here: the module
59 will be called snd-ali5451. 59 will be called snd-ali5451.
60 60
61config SND_ASIHPI
62 tristate "AudioScience ASIxxxx"
63 depends on X86
64 select FW_LOADER
65 select SND_PCM
66 select SND_HWDEP
67 help
68 Say Y here to include support for AudioScience ASI sound cards.
69
70 To compile this driver as a module, choose M here: the module
71 will be called snd-asihpi.
72
61config SND_ATIIXP 73config SND_ATIIXP
62 tristate "ATI IXP AC97 Controller" 74 tristate "ATI IXP AC97 Controller"
63 select SND_AC97_CODEC 75 select SND_AC97_CODEC
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index ecfc609d2b9f..9cf4348ec137 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_SND_VIA82XX_MODEM) += snd-via82xx-modem.o
57obj-$(CONFIG_SND) += \ 57obj-$(CONFIG_SND) += \
58 ac97/ \ 58 ac97/ \
59 ali5451/ \ 59 ali5451/ \
60 asihpi/ \
60 au88x0/ \ 61 au88x0/ \
61 aw2/ \ 62 aw2/ \
62 ctxfi/ \ 63 ctxfi/ \
diff --git a/sound/pci/asihpi/Makefile b/sound/pci/asihpi/Makefile
new file mode 100644
index 000000000000..391830a4556c
--- /dev/null
+++ b/sound/pci/asihpi/Makefile
@@ -0,0 +1,5 @@
1snd-asihpi-objs := asihpi.o hpioctl.o hpimsginit.o\
2 hpicmn.o hpifunc.o hpidebug.o hpidspcd.o\
3 hpios.o hpi6000.o hpi6205.o hpimsgx.o
4
5obj-$(CONFIG_SND_ASIHPI) += snd-asihpi.o
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
new file mode 100644
index 000000000000..f74c7372b3d1
--- /dev/null
+++ b/sound/pci/asihpi/asihpi.c
@@ -0,0 +1,3002 @@
1/*
2 * Asihpi soundcard
3 * Copyright (c) by AudioScience Inc <alsa@audioscience.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 *
19 * The following is not a condition of use, merely a request:
20 * If you modify this program, particularly if you fix errors, AudioScience Inc
21 * would appreciate it if you grant us the right to use those modifications
22 * for any purpose including commercial applications.
23 */
24/* >0: print Hw params, timer vars. >1: print stream write/copy sizes */
25#define REALLY_VERBOSE_LOGGING 0
26
27#if REALLY_VERBOSE_LOGGING
28#define VPRINTK1 snd_printd
29#else
30#define VPRINTK1(...)
31#endif
32
33#if REALLY_VERBOSE_LOGGING > 1
34#define VPRINTK2 snd_printd
35#else
36#define VPRINTK2(...)
37#endif
38
39#ifndef ASI_STYLE_NAMES
40/* not sure how ALSA style name should look */
41#define ASI_STYLE_NAMES 1
42#endif
43
44#include "hpi_internal.h"
45#include "hpimsginit.h"
46#include "hpioctl.h"
47
48#include <linux/pci.h>
49#include <linux/init.h>
50#include <linux/jiffies.h>
51#include <linux/slab.h>
52#include <linux/time.h>
53#include <linux/wait.h>
54#include <sound/core.h>
55#include <sound/control.h>
56#include <sound/pcm.h>
57#include <sound/pcm_params.h>
58#include <sound/info.h>
59#include <sound/initval.h>
60#include <sound/tlv.h>
61#include <sound/hwdep.h>
62
63
64MODULE_LICENSE("GPL");
65MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
66MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
67
68static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */
69static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
70static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
71static int enable_hpi_hwdep = 1;
72
73module_param_array(index, int, NULL, S_IRUGO);
74MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard.");
75
76module_param_array(id, charp, NULL, S_IRUGO);
77MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard.");
78
79module_param_array(enable, bool, NULL, S_IRUGO);
80MODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard.");
81
82module_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR);
83MODULE_PARM_DESC(enable_hpi_hwdep,
84 "ALSA enable HPI hwdep for AudioScience soundcard ");
85
86/* identify driver */
87#ifdef KERNEL_ALSA_BUILD
88static char *build_info = "built using headers from kernel source";
89module_param(build_info, charp, S_IRUGO);
90MODULE_PARM_DESC(build_info, "built using headers from kernel source");
91#else
92static char *build_info = "built within ALSA source";
93module_param(build_info, charp, S_IRUGO);
94MODULE_PARM_DESC(build_info, "built within ALSA source");
95#endif
96
97/* set to 1 to dump every control from adapter to log */
98static const int mixer_dump;
99
100#define DEFAULT_SAMPLERATE 44100
101static int adapter_fs = DEFAULT_SAMPLERATE;
102
103static struct hpi_hsubsys *ss; /* handle to HPI audio subsystem */
104
105/* defaults */
106#define PERIODS_MIN 2
107#define PERIOD_BYTES_MIN 2304
108#define BUFFER_BYTES_MAX (512 * 1024)
109
110/*#define TIMER_MILLISECONDS 20
111#define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000)
112*/
113
114#define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7)
115
116struct clk_source {
117 int source;
118 int index;
119 char *name;
120};
121
122struct clk_cache {
123 int count;
124 int has_local;
125 struct clk_source s[MAX_CLOCKSOURCES];
126};
127
128/* Per card data */
129struct snd_card_asihpi {
130 struct snd_card *card;
131 struct pci_dev *pci;
132 u16 adapter_index;
133 u32 serial_number;
134 u16 type;
135 u16 version;
136 u16 num_outstreams;
137 u16 num_instreams;
138
139 u32 h_mixer;
140 struct clk_cache cc;
141
142 u16 support_mmap;
143 u16 support_grouping;
144 u16 support_mrx;
145 u16 update_interval_frames;
146 u16 in_max_chans;
147 u16 out_max_chans;
148};
149
150/* Per stream data */
151struct snd_card_asihpi_pcm {
152 struct timer_list timer;
153 unsigned int respawn_timer;
154 unsigned int hpi_buffer_attached;
155 unsigned int pcm_size;
156 unsigned int pcm_count;
157 unsigned int bytes_per_sec;
158 unsigned int pcm_irq_pos; /* IRQ position */
159 unsigned int pcm_buf_pos; /* position in buffer */
160 struct snd_pcm_substream *substream;
161 u32 h_stream;
162 struct hpi_format format;
163};
164
165/* universal stream verbs work with out or in stream handles */
166
167/* Functions to allow driver to give a buffer to HPI for busmastering */
168
169static u16 hpi_stream_host_buffer_attach(
170 struct hpi_hsubsys *hS,
171 u32 h_stream, /* handle to outstream. */
172 u32 size_in_bytes, /* size in bytes of bus mastering buffer */
173 u32 pci_address
174)
175{
176 struct hpi_message hm;
177 struct hpi_response hr;
178 unsigned int obj = hpi_handle_object(h_stream);
179
180 if (!h_stream)
181 return HPI_ERROR_INVALID_OBJ;
182 hpi_init_message_response(&hm, &hr, obj,
183 obj == HPI_OBJ_OSTREAM ?
184 HPI_OSTREAM_HOSTBUFFER_ALLOC :
185 HPI_ISTREAM_HOSTBUFFER_ALLOC);
186
187 hpi_handle_to_indexes(h_stream, &hm.adapter_index,
188 &hm.obj_index);
189
190 hm.u.d.u.buffer.buffer_size = size_in_bytes;
191 hm.u.d.u.buffer.pci_address = pci_address;
192 hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER;
193 hpi_send_recv(&hm, &hr);
194 return hr.error;
195}
196
197static u16 hpi_stream_host_buffer_detach(
198 struct hpi_hsubsys *hS,
199 u32 h_stream
200)
201{
202 struct hpi_message hm;
203 struct hpi_response hr;
204 unsigned int obj = hpi_handle_object(h_stream);
205
206 if (!h_stream)
207 return HPI_ERROR_INVALID_OBJ;
208
209 hpi_init_message_response(&hm, &hr, obj,
210 obj == HPI_OBJ_OSTREAM ?
211 HPI_OSTREAM_HOSTBUFFER_FREE :
212 HPI_ISTREAM_HOSTBUFFER_FREE);
213
214 hpi_handle_to_indexes(h_stream, &hm.adapter_index,
215 &hm.obj_index);
216 hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER;
217 hpi_send_recv(&hm, &hr);
218 return hr.error;
219}
220
221static inline u16 hpi_stream_start(struct hpi_hsubsys *hS, u32 h_stream)
222{
223 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
224 return hpi_outstream_start(hS, h_stream);
225 else
226 return hpi_instream_start(hS, h_stream);
227}
228
229static inline u16 hpi_stream_stop(struct hpi_hsubsys *hS, u32 h_stream)
230{
231 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
232 return hpi_outstream_stop(hS, h_stream);
233 else
234 return hpi_instream_stop(hS, h_stream);
235}
236
237static inline u16 hpi_stream_get_info_ex(
238 struct hpi_hsubsys *hS,
239 u32 h_stream,
240 u16 *pw_state,
241 u32 *pbuffer_size,
242 u32 *pdata_in_buffer,
243 u32 *psample_count,
244 u32 *pauxiliary_data
245)
246{
247 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
248 return hpi_outstream_get_info_ex(hS, h_stream, pw_state,
249 pbuffer_size, pdata_in_buffer,
250 psample_count, pauxiliary_data);
251 else
252 return hpi_instream_get_info_ex(hS, h_stream, pw_state,
253 pbuffer_size, pdata_in_buffer,
254 psample_count, pauxiliary_data);
255}
256
257static inline u16 hpi_stream_group_add(struct hpi_hsubsys *hS,
258 u32 h_master,
259 u32 h_stream)
260{
261 if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM)
262 return hpi_outstream_group_add(hS, h_master, h_stream);
263 else
264 return hpi_instream_group_add(hS, h_master, h_stream);
265}
266
267static inline u16 hpi_stream_group_reset(struct hpi_hsubsys *hS,
268 u32 h_stream)
269{
270 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
271 return hpi_outstream_group_reset(hS, h_stream);
272 else
273 return hpi_instream_group_reset(hS, h_stream);
274}
275
276static inline u16 hpi_stream_group_get_map(struct hpi_hsubsys *hS,
277 u32 h_stream, u32 *mo, u32 *mi)
278{
279 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
280 return hpi_outstream_group_get_map(hS, h_stream, mo, mi);
281 else
282 return hpi_instream_group_get_map(hS, h_stream, mo, mi);
283}
284
285static u16 handle_error(u16 err, int line, char *filename)
286{
287 if (err)
288 printk(KERN_WARNING
289 "in file %s, line %d: HPI error %d\n",
290 filename, line, err);
291 return err;
292}
293
294#define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__)
295
296/***************************** GENERAL PCM ****************/
297#if REALLY_VERBOSE_LOGGING
298static void print_hwparams(struct snd_pcm_hw_params *p)
299{
300 snd_printd("HWPARAMS \n");
301 snd_printd("samplerate %d \n", params_rate(p));
302 snd_printd("channels %d \n", params_channels(p));
303 snd_printd("format %d \n", params_format(p));
304 snd_printd("subformat %d \n", params_subformat(p));
305 snd_printd("buffer bytes %d \n", params_buffer_bytes(p));
306 snd_printd("period bytes %d \n", params_period_bytes(p));
307 snd_printd("access %d \n", params_access(p));
308 snd_printd("period_size %d \n", params_period_size(p));
309 snd_printd("periods %d \n", params_periods(p));
310 snd_printd("buffer_size %d \n", params_buffer_size(p));
311}
312#else
313#define print_hwparams(x)
314#endif
315
316static snd_pcm_format_t hpi_to_alsa_formats[] = {
317 -1, /* INVALID */
318 SNDRV_PCM_FORMAT_U8, /* HPI_FORMAT_PCM8_UNSIGNED 1 */
319 SNDRV_PCM_FORMAT_S16, /* HPI_FORMAT_PCM16_SIGNED 2 */
320 -1, /* HPI_FORMAT_MPEG_L1 3 */
321 SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L2 4 */
322 SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L3 5 */
323 -1, /* HPI_FORMAT_DOLBY_AC2 6 */
324 -1, /* HPI_FORMAT_DOLBY_AC3 7 */
325 SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN 8 */
326 -1, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */
327 -1, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */
328 SNDRV_PCM_FORMAT_S32, /* HPI_FORMAT_PCM32_SIGNED 11 */
329 -1, /* HPI_FORMAT_RAW_BITSTREAM 12 */
330 -1, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */
331 SNDRV_PCM_FORMAT_FLOAT, /* HPI_FORMAT_PCM32_FLOAT 14 */
332#if 1
333 /* ALSA can't handle 3 byte sample size together with power-of-2
334 * constraint on buffer_bytes, so disable this format
335 */
336 -1
337#else
338 /* SNDRV_PCM_FORMAT_S24_3LE */ /* { HPI_FORMAT_PCM24_SIGNED 15 */
339#endif
340};
341
342
343static int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format,
344 u16 *hpi_format)
345{
346 u16 format;
347
348 for (format = HPI_FORMAT_PCM8_UNSIGNED;
349 format <= HPI_FORMAT_PCM24_SIGNED; format++) {
350 if (hpi_to_alsa_formats[format] == alsa_format) {
351 *hpi_format = format;
352 return 0;
353 }
354 }
355
356 snd_printd(KERN_WARNING "failed match for alsa format %d\n",
357 alsa_format);
358 *hpi_format = 0;
359 return -EINVAL;
360}
361
362static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
363 struct snd_pcm_hardware *pcmhw)
364{
365 u16 err;
366 u32 h_control;
367 u32 sample_rate;
368 int idx;
369 unsigned int rate_min = 200000;
370 unsigned int rate_max = 0;
371 unsigned int rates = 0;
372
373 if (asihpi->support_mrx) {
374 rates |= SNDRV_PCM_RATE_CONTINUOUS;
375 rates |= SNDRV_PCM_RATE_8000_96000;
376 rate_min = 8000;
377 rate_max = 100000;
378 } else {
379 /* on cards without SRC,
380 valid rates are determined by sampleclock */
381 err = hpi_mixer_get_control(ss, asihpi->h_mixer,
382 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
383 HPI_CONTROL_SAMPLECLOCK, &h_control);
384 if (err) {
385 snd_printk(KERN_ERR
386 "no local sampleclock, err %d\n", err);
387 }
388
389 for (idx = 0; idx < 100; idx++) {
390 if (hpi_sample_clock_query_local_rate(ss,
391 h_control, idx, &sample_rate)) {
392 if (!idx)
393 snd_printk(KERN_ERR
394 "local rate query failed\n");
395
396 break;
397 }
398
399 rate_min = min(rate_min, sample_rate);
400 rate_max = max(rate_max, sample_rate);
401
402 switch (sample_rate) {
403 case 5512:
404 rates |= SNDRV_PCM_RATE_5512;
405 break;
406 case 8000:
407 rates |= SNDRV_PCM_RATE_8000;
408 break;
409 case 11025:
410 rates |= SNDRV_PCM_RATE_11025;
411 break;
412 case 16000:
413 rates |= SNDRV_PCM_RATE_16000;
414 break;
415 case 22050:
416 rates |= SNDRV_PCM_RATE_22050;
417 break;
418 case 32000:
419 rates |= SNDRV_PCM_RATE_32000;
420 break;
421 case 44100:
422 rates |= SNDRV_PCM_RATE_44100;
423 break;
424 case 48000:
425 rates |= SNDRV_PCM_RATE_48000;
426 break;
427 case 64000:
428 rates |= SNDRV_PCM_RATE_64000;
429 break;
430 case 88200:
431 rates |= SNDRV_PCM_RATE_88200;
432 break;
433 case 96000:
434 rates |= SNDRV_PCM_RATE_96000;
435 break;
436 case 176400:
437 rates |= SNDRV_PCM_RATE_176400;
438 break;
439 case 192000:
440 rates |= SNDRV_PCM_RATE_192000;
441 break;
442 default: /* some other rate */
443 rates |= SNDRV_PCM_RATE_KNOT;
444 }
445 }
446 }
447
448 /* printk(KERN_INFO "Supported rates %X %d %d\n",
449 rates, rate_min, rate_max); */
450 pcmhw->rates = rates;
451 pcmhw->rate_min = rate_min;
452 pcmhw->rate_max = rate_max;
453}
454
455static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
456 struct snd_pcm_hw_params *params)
457{
458 struct snd_pcm_runtime *runtime = substream->runtime;
459 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
460 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
461 int err;
462 u16 format;
463 unsigned int bytes_per_sec;
464
465 print_hwparams(params);
466 err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
467 if (err < 0)
468 return err;
469 err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format);
470 if (err)
471 return err;
472
473 VPRINTK1(KERN_INFO "format %d, %d chans, %d_hz\n",
474 format, params_channels(params),
475 params_rate(params));
476
477 hpi_handle_error(hpi_format_create(&dpcm->format,
478 params_channels(params),
479 format, params_rate(params), 0, 0));
480
481 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
482 if (hpi_instream_reset(ss, dpcm->h_stream) != 0)
483 return -EINVAL;
484
485 if (hpi_instream_set_format(ss,
486 dpcm->h_stream, &dpcm->format) != 0)
487 return -EINVAL;
488 }
489
490 dpcm->hpi_buffer_attached = 0;
491 if (card->support_mmap) {
492
493 err = hpi_stream_host_buffer_attach(ss, dpcm->h_stream,
494 params_buffer_bytes(params), runtime->dma_addr);
495 if (err == 0) {
496 snd_printd(KERN_INFO
497 "stream_host_buffer_attach succeeded %u %lu\n",
498 params_buffer_bytes(params),
499 (unsigned long)runtime->dma_addr);
500 } else {
501 snd_printd(KERN_INFO
502 "stream_host_buffer_attach error %d\n",
503 err);
504 return -ENOMEM;
505 }
506
507 err = hpi_stream_get_info_ex(ss, dpcm->h_stream, NULL,
508 &dpcm->hpi_buffer_attached,
509 NULL, NULL, NULL);
510
511 snd_printd(KERN_INFO "stream_host_buffer_attach status 0x%x\n",
512 dpcm->hpi_buffer_attached);
513 }
514 bytes_per_sec = params_rate(params) * params_channels(params);
515 bytes_per_sec *= snd_pcm_format_width(params_format(params));
516 bytes_per_sec /= 8;
517 if (bytes_per_sec <= 0)
518 return -EINVAL;
519
520 dpcm->bytes_per_sec = bytes_per_sec;
521 dpcm->pcm_size = params_buffer_bytes(params);
522 dpcm->pcm_count = params_period_bytes(params);
523 snd_printd(KERN_INFO "pcm_size=%d, pcm_count=%d, bps=%d\n",
524 dpcm->pcm_size, dpcm->pcm_count, bytes_per_sec);
525
526 dpcm->pcm_irq_pos = 0;
527 dpcm->pcm_buf_pos = 0;
528 return 0;
529}
530
531static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream *
532 substream)
533{
534 struct snd_pcm_runtime *runtime = substream->runtime;
535 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
536 int expiry;
537
538 expiry = (dpcm->pcm_count * HZ / dpcm->bytes_per_sec);
539 /* wait longer the first time, for samples to propagate */
540 expiry = max(expiry, 20);
541 dpcm->timer.expires = jiffies + expiry;
542 dpcm->respawn_timer = 1;
543 add_timer(&dpcm->timer);
544}
545
546static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream)
547{
548 struct snd_pcm_runtime *runtime = substream->runtime;
549 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
550
551 dpcm->respawn_timer = 0;
552 del_timer(&dpcm->timer);
553}
554
555static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
556 int cmd)
557{
558 struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;
559 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
560 struct snd_pcm_substream *s;
561 u16 e;
562
563 snd_printd("trigger %dstream %d\n",
564 substream->stream, substream->number);
565 switch (cmd) {
566 case SNDRV_PCM_TRIGGER_START:
567 snd_pcm_group_for_each_entry(s, substream) {
568 struct snd_card_asihpi_pcm *ds;
569 ds = s->runtime->private_data;
570
571 if (snd_pcm_substream_chip(s) != card)
572 continue;
573
574 if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
575 (card->support_mmap)) {
576 /* How do I know how much valid data is present
577 * in buffer? Just guessing 2 periods, but if
578 * buffer is bigger it may contain even more
579 * data??
580 */
581 unsigned int preload = ds->pcm_count * 2;
582 VPRINTK2("preload %d\n", preload);
583 hpi_handle_error(hpi_outstream_write_buf(
584 ss, ds->h_stream,
585 &s->runtime->dma_area[0],
586 preload,
587 &ds->format));
588 }
589
590 if (card->support_grouping) {
591 VPRINTK1("\t_group %dstream %d\n", s->stream,
592 s->number);
593 e = hpi_stream_group_add(ss,
594 dpcm->h_stream,
595 ds->h_stream);
596 if (!e) {
597 snd_pcm_trigger_done(s, substream);
598 } else {
599 hpi_handle_error(e);
600 break;
601 }
602 } else
603 break;
604 }
605 snd_printd("start\n");
606 /* start the master stream */
607 snd_card_asihpi_pcm_timer_start(substream);
608 hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream));
609 break;
610
611 case SNDRV_PCM_TRIGGER_STOP:
612 snd_card_asihpi_pcm_timer_stop(substream);
613 snd_pcm_group_for_each_entry(s, substream) {
614 if (snd_pcm_substream_chip(s) != card)
615 continue;
616
617 /*? workaround linked streams don't
618 transition to SETUP 20070706*/
619 s->runtime->status->state = SNDRV_PCM_STATE_SETUP;
620
621 if (card->support_grouping) {
622 VPRINTK1("\t_group %dstream %d\n", s->stream,
623 s->number);
624 snd_pcm_trigger_done(s, substream);
625 } else
626 break;
627 }
628 snd_printd("stop\n");
629
630 /* _prepare and _hwparams reset the stream */
631 hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream));
632 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
633 hpi_handle_error(
634 hpi_outstream_reset(ss, dpcm->h_stream));
635
636 if (card->support_grouping)
637 hpi_handle_error(hpi_stream_group_reset(ss,
638 dpcm->h_stream));
639 break;
640
641 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
642 snd_printd("pause release\n");
643 hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream));
644 snd_card_asihpi_pcm_timer_start(substream);
645 break;
646 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
647 snd_printd("pause\n");
648 snd_card_asihpi_pcm_timer_stop(substream);
649 hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream));
650 break;
651 default:
652 snd_printd("\tINVALID\n");
653 return -EINVAL;
654 }
655
656 return 0;
657}
658
659static int
660snd_card_asihpi_hw_free(struct snd_pcm_substream *substream)
661{
662 struct snd_pcm_runtime *runtime = substream->runtime;
663 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
664 if (dpcm->hpi_buffer_attached)
665 hpi_stream_host_buffer_detach(ss, dpcm->h_stream);
666
667 snd_pcm_lib_free_pages(substream);
668 return 0;
669}
670
671static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime)
672{
673 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
674 kfree(dpcm);
675}
676
677/*algorithm outline
678 Without linking degenerates to getting single stream pos etc
679 Without mmap 2nd loop degenerates to snd_pcm_period_elapsed
680*/
681/*
682buf_pos=get_buf_pos(s);
683for_each_linked_stream(s) {
684 buf_pos=get_buf_pos(s);
685 min_buf_pos = modulo_min(min_buf_pos, buf_pos, pcm_size)
686 new_data = min(new_data, calc_new_data(buf_pos,irq_pos)
687}
688timer.expires = jiffies + predict_next_period_ready(min_buf_pos);
689for_each_linked_stream(s) {
690 s->buf_pos = min_buf_pos;
691 if (new_data > pcm_count) {
692 if (mmap) {
693 irq_pos = (irq_pos + pcm_count) % pcm_size;
694 if (playback) {
695 write(pcm_count);
696 } else {
697 read(pcm_count);
698 }
699 }
700 snd_pcm_period_elapsed(s);
701 }
702}
703*/
704
705/** Minimum of 2 modulo values. Works correctly when the difference between
706* the values is less than half the modulus
707*/
708static inline unsigned int modulo_min(unsigned int a, unsigned int b,
709 unsigned long int modulus)
710{
711 unsigned int result;
712 if (((a-b) % modulus) < (modulus/2))
713 result = b;
714 else
715 result = a;
716
717 return result;
718}
719
720/** Timer function, equivalent to interrupt service routine for cards
721*/
722static void snd_card_asihpi_timer_function(unsigned long data)
723{
724 struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data;
725 struct snd_card_asihpi *card = snd_pcm_substream_chip(dpcm->substream);
726 struct snd_pcm_runtime *runtime;
727 struct snd_pcm_substream *s;
728 unsigned int newdata = 0;
729 unsigned int buf_pos, min_buf_pos = 0;
730 unsigned int remdata, xfercount, next_jiffies;
731 int first = 1;
732 u16 state;
733 u32 buffer_size, data_avail, samples_played, aux;
734
735 /* find minimum newdata and buffer pos in group */
736 snd_pcm_group_for_each_entry(s, dpcm->substream) {
737 struct snd_card_asihpi_pcm *ds = s->runtime->private_data;
738 runtime = s->runtime;
739
740 if (snd_pcm_substream_chip(s) != card)
741 continue;
742
743 hpi_handle_error(hpi_stream_get_info_ex(ss,
744 ds->h_stream, &state,
745 &buffer_size, &data_avail,
746 &samples_played, &aux));
747
748 /* number of bytes in on-card buffer */
749 runtime->delay = aux;
750
751 if (state == HPI_STATE_DRAINED) {
752 snd_printd(KERN_WARNING "outstream %d drained\n",
753 s->number);
754 snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
755 return;
756 }
757
758 if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
759 buf_pos = frames_to_bytes(runtime, samples_played);
760 } else {
761 buf_pos = data_avail + ds->pcm_irq_pos;
762 }
763
764 if (first) {
765 /* can't statically init min when wrap is involved */
766 min_buf_pos = buf_pos;
767 newdata = (buf_pos - ds->pcm_irq_pos) % ds->pcm_size;
768 first = 0;
769 } else {
770 min_buf_pos =
771 modulo_min(min_buf_pos, buf_pos, UINT_MAX+1L);
772 newdata = min(
773 (buf_pos - ds->pcm_irq_pos) % ds->pcm_size,
774 newdata);
775 }
776
777 VPRINTK1("PB timer hw_ptr x%04lX, appl_ptr x%04lX\n",
778 (unsigned long)frames_to_bytes(runtime,
779 runtime->status->hw_ptr),
780 (unsigned long)frames_to_bytes(runtime,
781 runtime->control->appl_ptr));
782 VPRINTK1("%d S=%d, irq=%04X, pos=x%04X, left=x%04X,"
783 " aux=x%04X space=x%04X\n", s->number,
784 state, ds->pcm_irq_pos, buf_pos, (int)data_avail,
785 (int)aux, buffer_size-data_avail);
786 }
787
788 remdata = newdata % dpcm->pcm_count;
789 xfercount = newdata - remdata; /* a multiple of pcm_count */
790 next_jiffies = ((dpcm->pcm_count-remdata) * HZ / dpcm->bytes_per_sec)+1;
791 next_jiffies = max(next_jiffies, 2U * HZ / 1000U);
792 dpcm->timer.expires = jiffies + next_jiffies;
793 VPRINTK1("jif %d buf pos x%04X newdata x%04X xc x%04X\n",
794 next_jiffies, min_buf_pos, newdata, xfercount);
795
796 snd_pcm_group_for_each_entry(s, dpcm->substream) {
797 struct snd_card_asihpi_pcm *ds = s->runtime->private_data;
798 ds->pcm_buf_pos = min_buf_pos;
799
800 if (xfercount) {
801 if (card->support_mmap) {
802 ds->pcm_irq_pos = ds->pcm_irq_pos + xfercount;
803 if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
804 VPRINTK2("write OS%d x%04x\n",
805 s->number,
806 ds->pcm_count);
807 hpi_handle_error(
808 hpi_outstream_write_buf(
809 ss, ds->h_stream,
810 &s->runtime->
811 dma_area[0],
812 xfercount,
813 &ds->format));
814 } else {
815 VPRINTK2("read IS%d x%04x\n",
816 s->number,
817 dpcm->pcm_count);
818 hpi_handle_error(
819 hpi_instream_read_buf(
820 ss, ds->h_stream,
821 NULL, xfercount));
822 }
823 } /* else R/W will be handled by read/write callbacks */
824 snd_pcm_period_elapsed(s);
825 }
826 }
827
828 if (dpcm->respawn_timer)
829 add_timer(&dpcm->timer);
830}
831
832/***************************** PLAYBACK OPS ****************/
833static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream,
834 unsigned int cmd, void *arg)
835{
836 /* snd_printd(KERN_INFO "Playback ioctl %d\n", cmd); */
837 return snd_pcm_lib_ioctl(substream, cmd, arg);
838}
839
840static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
841 substream)
842{
843 struct snd_pcm_runtime *runtime = substream->runtime;
844 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
845
846 snd_printd(KERN_INFO "playback prepare %d\n", substream->number);
847
848 hpi_handle_error(hpi_outstream_reset(ss, dpcm->h_stream));
849 dpcm->pcm_irq_pos = 0;
850 dpcm->pcm_buf_pos = 0;
851
852 return 0;
853}
854
855static snd_pcm_uframes_t
856snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
857{
858 struct snd_pcm_runtime *runtime = substream->runtime;
859 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
860 snd_pcm_uframes_t ptr;
861
862 u32 samples_played;
863 u16 err;
864
865 if (!snd_pcm_stream_linked(substream)) {
866 /* NOTE, can use samples played for playback position here and
867 * in timer fn because it LAGS the actual read pointer, and is a
868 * better representation of actual playout position
869 */
870 err = hpi_outstream_get_info_ex(ss, dpcm->h_stream, NULL,
871 NULL, NULL,
872 &samples_played, NULL);
873 hpi_handle_error(err);
874
875 dpcm->pcm_buf_pos = frames_to_bytes(runtime, samples_played);
876 }
877 /* else must return most conservative value found in timer func
878 * by looping over all streams
879 */
880
881 ptr = bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size);
882 VPRINTK2("playback_pointer=%04ld\n", (unsigned long)ptr);
883 return ptr;
884}
885
886static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
887 u32 h_stream,
888 struct snd_pcm_hardware *pcmhw)
889{
890 struct hpi_format hpi_format;
891 u16 format;
892 u16 err;
893 u32 h_control;
894 u32 sample_rate = 48000;
895
896 /* on cards without SRC, must query at valid rate,
897 * maybe set by external sync
898 */
899 err = hpi_mixer_get_control(ss, asihpi->h_mixer,
900 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
901 HPI_CONTROL_SAMPLECLOCK, &h_control);
902
903 if (!err)
904 err = hpi_sample_clock_get_sample_rate(ss, h_control,
905 &sample_rate);
906
907 for (format = HPI_FORMAT_PCM8_UNSIGNED;
908 format <= HPI_FORMAT_PCM24_SIGNED; format++) {
909 err = hpi_format_create(&hpi_format,
910 2, format, sample_rate, 128000, 0);
911 if (!err)
912 err = hpi_outstream_query_format(ss, h_stream,
913 &hpi_format);
914 if (!err && (hpi_to_alsa_formats[format] != -1))
915 pcmhw->formats |=
916 (1ULL << hpi_to_alsa_formats[format]);
917 }
918}
919
920static struct snd_pcm_hardware snd_card_asihpi_playback = {
921 .channels_min = 1,
922 .channels_max = 2,
923 .buffer_bytes_max = BUFFER_BYTES_MAX,
924 .period_bytes_min = PERIOD_BYTES_MIN,
925 .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
926 .periods_min = PERIODS_MIN,
927 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
928 .fifo_size = 0,
929};
930
931static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
932{
933 struct snd_pcm_runtime *runtime = substream->runtime;
934 struct snd_card_asihpi_pcm *dpcm;
935 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
936 int err;
937
938 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
939 if (dpcm == NULL)
940 return -ENOMEM;
941
942 err =
943 hpi_outstream_open(ss, card->adapter_index,
944 substream->number, &dpcm->h_stream);
945 hpi_handle_error(err);
946 if (err)
947 kfree(dpcm);
948 if (err == HPI_ERROR_OBJ_ALREADY_OPEN)
949 return -EBUSY;
950 if (err)
951 return -EIO;
952
953 /*? also check ASI5000 samplerate source
954 If external, only support external rate.
955 If internal and other stream playing, cant switch
956 */
957
958 init_timer(&dpcm->timer);
959 dpcm->timer.data = (unsigned long) dpcm;
960 dpcm->timer.function = snd_card_asihpi_timer_function;
961 dpcm->substream = substream;
962 runtime->private_data = dpcm;
963 runtime->private_free = snd_card_asihpi_runtime_free;
964
965 snd_card_asihpi_playback.channels_max = card->out_max_chans;
966 /*?snd_card_asihpi_playback.period_bytes_min =
967 card->out_max_chans * 4096; */
968
969 snd_card_asihpi_playback_format(card, dpcm->h_stream,
970 &snd_card_asihpi_playback);
971
972 snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_playback);
973
974 snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED |
975 SNDRV_PCM_INFO_DOUBLE |
976 SNDRV_PCM_INFO_BATCH |
977 SNDRV_PCM_INFO_BLOCK_TRANSFER |
978 SNDRV_PCM_INFO_PAUSE;
979
980 if (card->support_mmap)
981 snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_MMAP |
982 SNDRV_PCM_INFO_MMAP_VALID;
983
984 if (card->support_grouping)
985 snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START;
986
987 /* struct is copied, so can create initializer dynamically */
988 runtime->hw = snd_card_asihpi_playback;
989
990 if (card->support_mmap)
991 err = snd_pcm_hw_constraint_pow2(runtime, 0,
992 SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
993 if (err < 0)
994 return err;
995
996 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
997 card->update_interval_frames);
998 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
999 card->update_interval_frames * 4, UINT_MAX);
1000
1001 snd_pcm_set_sync(substream);
1002
1003 snd_printd(KERN_INFO "playback open\n");
1004
1005 return 0;
1006}
1007
1008static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
1009{
1010 struct snd_pcm_runtime *runtime = substream->runtime;
1011 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1012
1013 hpi_handle_error(hpi_outstream_close(ss, dpcm->h_stream));
1014 snd_printd(KERN_INFO "playback close\n");
1015
1016 return 0;
1017}
1018
1019static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream,
1020 int channel,
1021 snd_pcm_uframes_t pos,
1022 void __user *src,
1023 snd_pcm_uframes_t count)
1024{
1025 struct snd_pcm_runtime *runtime = substream->runtime;
1026 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1027 unsigned int len;
1028
1029 len = frames_to_bytes(runtime, count);
1030
1031 if (copy_from_user(runtime->dma_area, src, len))
1032 return -EFAULT;
1033
1034 VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n",
1035 substream->number, len);
1036
1037 hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream,
1038 runtime->dma_area, len, &dpcm->format));
1039
1040 return 0;
1041}
1042
1043static int snd_card_asihpi_playback_silence(struct snd_pcm_substream *
1044 substream, int channel,
1045 snd_pcm_uframes_t pos,
1046 snd_pcm_uframes_t count)
1047{
1048 unsigned int len;
1049 struct snd_pcm_runtime *runtime = substream->runtime;
1050 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1051
1052 len = frames_to_bytes(runtime, count);
1053 snd_printd(KERN_INFO "playback silence %u bytes\n", len);
1054
1055 memset(runtime->dma_area, 0, len);
1056 hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream,
1057 runtime->dma_area, len, &dpcm->format));
1058 return 0;
1059}
1060
1061static struct snd_pcm_ops snd_card_asihpi_playback_ops = {
1062 .open = snd_card_asihpi_playback_open,
1063 .close = snd_card_asihpi_playback_close,
1064 .ioctl = snd_card_asihpi_playback_ioctl,
1065 .hw_params = snd_card_asihpi_pcm_hw_params,
1066 .hw_free = snd_card_asihpi_hw_free,
1067 .prepare = snd_card_asihpi_playback_prepare,
1068 .trigger = snd_card_asihpi_trigger,
1069 .pointer = snd_card_asihpi_playback_pointer,
1070 .copy = snd_card_asihpi_playback_copy,
1071 .silence = snd_card_asihpi_playback_silence,
1072};
1073
1074static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {
1075 .open = snd_card_asihpi_playback_open,
1076 .close = snd_card_asihpi_playback_close,
1077 .ioctl = snd_card_asihpi_playback_ioctl,
1078 .hw_params = snd_card_asihpi_pcm_hw_params,
1079 .hw_free = snd_card_asihpi_hw_free,
1080 .prepare = snd_card_asihpi_playback_prepare,
1081 .trigger = snd_card_asihpi_trigger,
1082 .pointer = snd_card_asihpi_playback_pointer,
1083};
1084
1085/***************************** CAPTURE OPS ****************/
1086static snd_pcm_uframes_t
1087snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream)
1088{
1089 struct snd_pcm_runtime *runtime = substream->runtime;
1090 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1091
1092 VPRINTK2("capture pointer %d=%d\n",
1093 substream->number, dpcm->pcm_buf_pos);
1094 /* NOTE Unlike playback can't use actual dwSamplesPlayed
1095 for the capture position, because those samples aren't yet in
1096 the local buffer available for reading.
1097 */
1098 return bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size);
1099}
1100
1101static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream,
1102 unsigned int cmd, void *arg)
1103{
1104 return snd_pcm_lib_ioctl(substream, cmd, arg);
1105}
1106
1107static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
1108{
1109 struct snd_pcm_runtime *runtime = substream->runtime;
1110 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1111
1112 hpi_handle_error(hpi_instream_reset(ss, dpcm->h_stream));
1113 dpcm->pcm_irq_pos = 0;
1114 dpcm->pcm_buf_pos = 0;
1115
1116 snd_printd("capture prepare %d\n", substream->number);
1117 return 0;
1118}
1119
1120
1121
1122static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
1123 u32 h_stream,
1124 struct snd_pcm_hardware *pcmhw)
1125{
1126 struct hpi_format hpi_format;
1127 u16 format;
1128 u16 err;
1129 u32 h_control;
1130 u32 sample_rate = 48000;
1131
1132 /* on cards without SRC, must query at valid rate,
1133 maybe set by external sync */
1134 err = hpi_mixer_get_control(ss, asihpi->h_mixer,
1135 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
1136 HPI_CONTROL_SAMPLECLOCK, &h_control);
1137
1138 if (!err)
1139 err = hpi_sample_clock_get_sample_rate(ss, h_control,
1140 &sample_rate);
1141
1142 for (format = HPI_FORMAT_PCM8_UNSIGNED;
1143 format <= HPI_FORMAT_PCM24_SIGNED; format++) {
1144
1145 err = hpi_format_create(&hpi_format, 2, format,
1146 sample_rate, 128000, 0);
1147 if (!err)
1148 err = hpi_instream_query_format(ss, h_stream,
1149 &hpi_format);
1150 if (!err)
1151 pcmhw->formats |=
1152 (1ULL << hpi_to_alsa_formats[format]);
1153 }
1154}
1155
1156
1157static struct snd_pcm_hardware snd_card_asihpi_capture = {
1158 .channels_min = 1,
1159 .channels_max = 2,
1160 .buffer_bytes_max = BUFFER_BYTES_MAX,
1161 .period_bytes_min = PERIOD_BYTES_MIN,
1162 .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
1163 .periods_min = PERIODS_MIN,
1164 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
1165 .fifo_size = 0,
1166};
1167
1168static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
1169{
1170 struct snd_pcm_runtime *runtime = substream->runtime;
1171 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
1172 struct snd_card_asihpi_pcm *dpcm;
1173 int err;
1174
1175 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
1176 if (dpcm == NULL)
1177 return -ENOMEM;
1178
1179 snd_printd("hpi_instream_open adapter %d stream %d\n",
1180 card->adapter_index, substream->number);
1181
1182 err = hpi_handle_error(
1183 hpi_instream_open(ss, card->adapter_index,
1184 substream->number, &dpcm->h_stream));
1185 if (err)
1186 kfree(dpcm);
1187 if (err == HPI_ERROR_OBJ_ALREADY_OPEN)
1188 return -EBUSY;
1189 if (err)
1190 return -EIO;
1191
1192
1193 init_timer(&dpcm->timer);
1194 dpcm->timer.data = (unsigned long) dpcm;
1195 dpcm->timer.function = snd_card_asihpi_timer_function;
1196 dpcm->substream = substream;
1197 runtime->private_data = dpcm;
1198 runtime->private_free = snd_card_asihpi_runtime_free;
1199
1200 snd_card_asihpi_capture.channels_max = card->in_max_chans;
1201 snd_card_asihpi_capture_format(card, dpcm->h_stream,
1202 &snd_card_asihpi_capture);
1203 snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture);
1204 snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED;
1205
1206 if (card->support_mmap)
1207 snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP |
1208 SNDRV_PCM_INFO_MMAP_VALID;
1209
1210 runtime->hw = snd_card_asihpi_capture;
1211
1212 if (card->support_mmap)
1213 err = snd_pcm_hw_constraint_pow2(runtime, 0,
1214 SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
1215 if (err < 0)
1216 return err;
1217
1218 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1219 card->update_interval_frames);
1220 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1221 card->update_interval_frames * 2, UINT_MAX);
1222
1223 snd_pcm_set_sync(substream);
1224
1225 return 0;
1226}
1227
1228static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)
1229{
1230 struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;
1231
1232 hpi_handle_error(hpi_instream_close(ss, dpcm->h_stream));
1233 return 0;
1234}
1235
1236static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream,
1237 int channel, snd_pcm_uframes_t pos,
1238 void __user *dst, snd_pcm_uframes_t count)
1239{
1240 struct snd_pcm_runtime *runtime = substream->runtime;
1241 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1242 u32 data_size;
1243
1244 data_size = frames_to_bytes(runtime, count);
1245
1246 VPRINTK2("capture copy%d %d bytes\n", substream->number, data_size);
1247 hpi_handle_error(hpi_instream_read_buf(ss, dpcm->h_stream,
1248 runtime->dma_area, data_size));
1249
1250 /* Used by capture_pointer */
1251 dpcm->pcm_irq_pos = dpcm->pcm_irq_pos + data_size;
1252
1253 if (copy_to_user(dst, runtime->dma_area, data_size))
1254 return -EFAULT;
1255
1256 return 0;
1257}
1258
1259static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
1260 .open = snd_card_asihpi_capture_open,
1261 .close = snd_card_asihpi_capture_close,
1262 .ioctl = snd_card_asihpi_capture_ioctl,
1263 .hw_params = snd_card_asihpi_pcm_hw_params,
1264 .hw_free = snd_card_asihpi_hw_free,
1265 .prepare = snd_card_asihpi_capture_prepare,
1266 .trigger = snd_card_asihpi_trigger,
1267 .pointer = snd_card_asihpi_capture_pointer,
1268};
1269
1270static struct snd_pcm_ops snd_card_asihpi_capture_ops = {
1271 .open = snd_card_asihpi_capture_open,
1272 .close = snd_card_asihpi_capture_close,
1273 .ioctl = snd_card_asihpi_capture_ioctl,
1274 .hw_params = snd_card_asihpi_pcm_hw_params,
1275 .hw_free = snd_card_asihpi_hw_free,
1276 .prepare = snd_card_asihpi_capture_prepare,
1277 .trigger = snd_card_asihpi_trigger,
1278 .pointer = snd_card_asihpi_capture_pointer,
1279 .copy = snd_card_asihpi_capture_copy
1280};
1281
1282static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
1283 int device, int substreams)
1284{
1285 struct snd_pcm *pcm;
1286 int err;
1287
1288 err = snd_pcm_new(asihpi->card, "asihpi PCM", device,
1289 asihpi->num_outstreams, asihpi->num_instreams,
1290 &pcm);
1291 if (err < 0)
1292 return err;
1293 /* pointer to ops struct is stored, dont change ops afterwards! */
1294 if (asihpi->support_mmap) {
1295 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1296 &snd_card_asihpi_playback_mmap_ops);
1297 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1298 &snd_card_asihpi_capture_mmap_ops);
1299 } else {
1300 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1301 &snd_card_asihpi_playback_ops);
1302 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1303 &snd_card_asihpi_capture_ops);
1304 }
1305
1306 pcm->private_data = asihpi;
1307 pcm->info_flags = 0;
1308 strcpy(pcm->name, "asihpi PCM");
1309
1310 /*? do we want to emulate MMAP for non-BBM cards?
1311 Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */
1312 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1313 snd_dma_pci_data(asihpi->pci),
1314 64*1024, BUFFER_BYTES_MAX);
1315
1316 return 0;
1317}
1318
1319/***************************** MIXER CONTROLS ****************/
1320struct hpi_control {
1321 u32 h_control;
1322 u16 control_type;
1323 u16 src_node_type;
1324 u16 src_node_index;
1325 u16 dst_node_type;
1326 u16 dst_node_index;
1327 u16 band;
1328 char name[44]; /* copied to snd_ctl_elem_id.name[44]; */
1329};
1330
1331static char *asihpi_tuner_band_names[] =
1332{
1333 "invalid",
1334 "AM",
1335 "FM mono",
1336 "TV NTSC-M",
1337 "FM stereo",
1338 "AUX",
1339 "TV PAL BG",
1340 "TV PAL I",
1341 "TV PAL DK",
1342 "TV SECAM",
1343};
1344
1345compile_time_assert(
1346 (ARRAY_SIZE(asihpi_tuner_band_names) ==
1347 (HPI_TUNER_BAND_LAST+1)),
1348 assert_tuner_band_names_size);
1349
1350#if ASI_STYLE_NAMES
1351static char *asihpi_src_names[] =
1352{
1353 "no source",
1354 "outstream",
1355 "line_in",
1356 "aes_in",
1357 "tuner",
1358 "RF",
1359 "clock",
1360 "bitstr",
1361 "mic",
1362 "cobranet",
1363 "analog_in",
1364 "adapter",
1365};
1366#else
1367static char *asihpi_src_names[] =
1368{
1369 "no source",
1370 "PCM playback",
1371 "line in",
1372 "digital in",
1373 "tuner",
1374 "RF",
1375 "clock",
1376 "bitstream",
1377 "mic",
1378 "cobranet in",
1379 "analog in",
1380 "adapter",
1381};
1382#endif
1383
1384compile_time_assert(
1385 (ARRAY_SIZE(asihpi_src_names) ==
1386 (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_BASE+1)),
1387 assert_src_names_size);
1388
1389#if ASI_STYLE_NAMES
1390static char *asihpi_dst_names[] =
1391{
1392 "no destination",
1393 "instream",
1394 "line_out",
1395 "aes_out",
1396 "RF",
1397 "speaker" ,
1398 "cobranet",
1399 "analog_out",
1400};
1401#else
1402static char *asihpi_dst_names[] =
1403{
1404 "no destination",
1405 "PCM capture",
1406 "line out",
1407 "digital out",
1408 "RF",
1409 "speaker",
1410 "cobranet out",
1411 "analog out"
1412};
1413#endif
1414
1415compile_time_assert(
1416 (ARRAY_SIZE(asihpi_dst_names) ==
1417 (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_BASE+1)),
1418 assert_dst_names_size);
1419
1420static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
1421 struct snd_card_asihpi *asihpi)
1422{
1423 int err;
1424
1425 err = snd_ctl_add(card, snd_ctl_new1(ctl, asihpi));
1426 if (err < 0)
1427 return err;
1428 else if (mixer_dump)
1429 snd_printk(KERN_INFO "added %s(%d)\n", ctl->name, ctl->index);
1430
1431 return 0;
1432}
1433
1434/* Convert HPI control name and location into ALSA control name */
1435static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control,
1436 struct hpi_control *hpi_ctl,
1437 char *name)
1438{
1439 memset(snd_control, 0, sizeof(*snd_control));
1440 snd_control->name = hpi_ctl->name;
1441 snd_control->private_value = hpi_ctl->h_control;
1442 snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1443 snd_control->index = 0;
1444
1445 if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type)
1446 sprintf(hpi_ctl->name, "%s%d to %s%d %s",
1447 asihpi_src_names[hpi_ctl->src_node_type],
1448 hpi_ctl->src_node_index,
1449 asihpi_dst_names[hpi_ctl->dst_node_type],
1450 hpi_ctl->dst_node_index,
1451 name);
1452 else if (hpi_ctl->dst_node_type) {
1453 sprintf(hpi_ctl->name, "%s%d %s",
1454 asihpi_dst_names[hpi_ctl->dst_node_type],
1455 hpi_ctl->dst_node_index,
1456 name);
1457 } else {
1458 sprintf(hpi_ctl->name, "%s%d %s",
1459 asihpi_src_names[hpi_ctl->src_node_type],
1460 hpi_ctl->src_node_index,
1461 name);
1462 }
1463}
1464
1465/*------------------------------------------------------------
1466 Volume controls
1467 ------------------------------------------------------------*/
1468#define VOL_STEP_mB 1
1469static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol,
1470 struct snd_ctl_elem_info *uinfo)
1471{
1472 u32 h_control = kcontrol->private_value;
1473 u16 err;
1474 /* native gains are in millibels */
1475 short min_gain_mB;
1476 short max_gain_mB;
1477 short step_gain_mB;
1478
1479 err = hpi_volume_query_range(ss, h_control,
1480 &min_gain_mB, &max_gain_mB, &step_gain_mB);
1481 if (err) {
1482 max_gain_mB = 0;
1483 min_gain_mB = -10000;
1484 step_gain_mB = VOL_STEP_mB;
1485 }
1486
1487 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1488 uinfo->count = 2;
1489 uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB;
1490 uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB;
1491 uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB;
1492 return 0;
1493}
1494
1495static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol,
1496 struct snd_ctl_elem_value *ucontrol)
1497{
1498 u32 h_control = kcontrol->private_value;
1499 short an_gain_mB[HPI_MAX_CHANNELS];
1500
1501 hpi_handle_error(hpi_volume_get_gain(ss, h_control, an_gain_mB));
1502 ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB;
1503 ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB;
1504
1505 return 0;
1506}
1507
1508static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol,
1509 struct snd_ctl_elem_value *ucontrol)
1510{
1511 int change;
1512 u32 h_control = kcontrol->private_value;
1513 short an_gain_mB[HPI_MAX_CHANNELS];
1514
1515 an_gain_mB[0] =
1516 (ucontrol->value.integer.value[0]) * VOL_STEP_mB;
1517 an_gain_mB[1] =
1518 (ucontrol->value.integer.value[1]) * VOL_STEP_mB;
1519 /* change = asihpi->mixer_volume[addr][0] != left ||
1520 asihpi->mixer_volume[addr][1] != right;
1521 */
1522 change = 1;
1523 hpi_handle_error(hpi_volume_set_gain(ss, h_control, an_gain_mB));
1524 return change;
1525}
1526
1527static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0);
1528
1529static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
1530 struct hpi_control *hpi_ctl)
1531{
1532 struct snd_card *card = asihpi->card;
1533 struct snd_kcontrol_new snd_control;
1534
1535 asihpi_ctl_init(&snd_control, hpi_ctl, "volume");
1536 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1537 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1538 snd_control.info = snd_asihpi_volume_info;
1539 snd_control.get = snd_asihpi_volume_get;
1540 snd_control.put = snd_asihpi_volume_put;
1541 snd_control.tlv.p = db_scale_100;
1542
1543 return ctl_add(card, &snd_control, asihpi);
1544}
1545
1546/*------------------------------------------------------------
1547 Level controls
1548 ------------------------------------------------------------*/
1549static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol,
1550 struct snd_ctl_elem_info *uinfo)
1551{
1552 u32 h_control = kcontrol->private_value;
1553 u16 err;
1554 short min_gain_mB;
1555 short max_gain_mB;
1556 short step_gain_mB;
1557
1558 err =
1559 hpi_level_query_range(ss, h_control, &min_gain_mB,
1560 &max_gain_mB, &step_gain_mB);
1561 if (err) {
1562 max_gain_mB = 2400;
1563 min_gain_mB = -1000;
1564 step_gain_mB = 100;
1565 }
1566
1567 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1568 uinfo->count = 2;
1569 uinfo->value.integer.min = min_gain_mB / HPI_UNITS_PER_dB;
1570 uinfo->value.integer.max = max_gain_mB / HPI_UNITS_PER_dB;
1571 uinfo->value.integer.step = step_gain_mB / HPI_UNITS_PER_dB;
1572 return 0;
1573}
1574
1575static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol,
1576 struct snd_ctl_elem_value *ucontrol)
1577{
1578 u32 h_control = kcontrol->private_value;
1579 short an_gain_mB[HPI_MAX_CHANNELS];
1580
1581 hpi_handle_error(hpi_level_get_gain(ss, h_control, an_gain_mB));
1582 ucontrol->value.integer.value[0] =
1583 an_gain_mB[0] / HPI_UNITS_PER_dB;
1584 ucontrol->value.integer.value[1] =
1585 an_gain_mB[1] / HPI_UNITS_PER_dB;
1586
1587 return 0;
1588}
1589
1590static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,
1591 struct snd_ctl_elem_value *ucontrol)
1592{
1593 int change;
1594 u32 h_control = kcontrol->private_value;
1595 short an_gain_mB[HPI_MAX_CHANNELS];
1596
1597 an_gain_mB[0] =
1598 (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;
1599 an_gain_mB[1] =
1600 (ucontrol->value.integer.value[1]) * HPI_UNITS_PER_dB;
1601 /* change = asihpi->mixer_level[addr][0] != left ||
1602 asihpi->mixer_level[addr][1] != right;
1603 */
1604 change = 1;
1605 hpi_handle_error(hpi_level_set_gain(ss, h_control, an_gain_mB));
1606 return change;
1607}
1608
1609static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0);
1610
1611static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
1612 struct hpi_control *hpi_ctl)
1613{
1614 struct snd_card *card = asihpi->card;
1615 struct snd_kcontrol_new snd_control;
1616
1617 /* can't use 'volume' cos some nodes have volume as well */
1618 asihpi_ctl_init(&snd_control, hpi_ctl, "level");
1619 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1620 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1621 snd_control.info = snd_asihpi_level_info;
1622 snd_control.get = snd_asihpi_level_get;
1623 snd_control.put = snd_asihpi_level_put;
1624 snd_control.tlv.p = db_scale_level;
1625
1626 return ctl_add(card, &snd_control, asihpi);
1627}
1628
1629/*------------------------------------------------------------
1630 AESEBU controls
1631 ------------------------------------------------------------*/
1632
1633/* AESEBU format */
1634static char *asihpi_aesebu_format_names[] =
1635{
1636 "N/A",
1637 "S/PDIF",
1638 "AES/EBU",
1639};
1640
1641static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_info *uinfo)
1643{
1644 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1645 uinfo->count = 1;
1646 uinfo->value.enumerated.items = 3;
1647
1648 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1649 uinfo->value.enumerated.item =
1650 uinfo->value.enumerated.items - 1;
1651
1652 strcpy(uinfo->value.enumerated.name,
1653 asihpi_aesebu_format_names[uinfo->value.enumerated.item]);
1654
1655 return 0;
1656}
1657
1658static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol,
1659 struct snd_ctl_elem_value *ucontrol,
1660 u16 (*func)(const struct hpi_hsubsys *, u32, u16 *))
1661{
1662 u32 h_control = kcontrol->private_value;
1663 u16 source, err;
1664
1665 err = func(ss, h_control, &source);
1666
1667 /* default to N/A */
1668 ucontrol->value.enumerated.item[0] = 0;
1669 /* return success but set the control to N/A */
1670 if (err)
1671 return 0;
1672 if (source == HPI_AESEBU_FORMAT_SPDIF)
1673 ucontrol->value.enumerated.item[0] = 1;
1674 if (source == HPI_AESEBU_FORMAT_AESEBU)
1675 ucontrol->value.enumerated.item[0] = 2;
1676
1677 return 0;
1678}
1679
1680static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol,
1681 struct snd_ctl_elem_value *ucontrol,
1682 u16 (*func)(const struct hpi_hsubsys *, u32, u16))
1683{
1684 u32 h_control = kcontrol->private_value;
1685
1686 /* default to S/PDIF */
1687 u16 source = HPI_AESEBU_FORMAT_SPDIF;
1688
1689 if (ucontrol->value.enumerated.item[0] == 1)
1690 source = HPI_AESEBU_FORMAT_SPDIF;
1691 if (ucontrol->value.enumerated.item[0] == 2)
1692 source = HPI_AESEBU_FORMAT_AESEBU;
1693
1694 if (func(ss, h_control, source) != 0)
1695 return -EINVAL;
1696
1697 return 1;
1698}
1699
1700static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol,
1701 struct snd_ctl_elem_value *ucontrol) {
1702 return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,
1703 HPI_AESEBU__receiver_get_format);
1704}
1705
1706static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol,
1707 struct snd_ctl_elem_value *ucontrol) {
1708 return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,
1709 HPI_AESEBU__receiver_set_format);
1710}
1711
1712static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol,
1713 struct snd_ctl_elem_info *uinfo)
1714{
1715 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1716 uinfo->count = 1;
1717
1718 uinfo->value.integer.min = 0;
1719 uinfo->value.integer.max = 0X1F;
1720 uinfo->value.integer.step = 1;
1721
1722 return 0;
1723}
1724
1725static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,
1726 struct snd_ctl_elem_value *ucontrol) {
1727
1728 u32 h_control = kcontrol->private_value;
1729 u16 status;
1730
1731 hpi_handle_error(HPI_AESEBU__receiver_get_error_status(
1732 ss, h_control, &status));
1733 ucontrol->value.integer.value[0] = status;
1734 return 0;
1735}
1736
1737static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
1738 struct hpi_control *hpi_ctl)
1739{
1740 struct snd_card *card = asihpi->card;
1741 struct snd_kcontrol_new snd_control;
1742
1743 asihpi_ctl_init(&snd_control, hpi_ctl, "format");
1744 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1745 snd_control.info = snd_asihpi_aesebu_format_info;
1746 snd_control.get = snd_asihpi_aesebu_rx_format_get;
1747 snd_control.put = snd_asihpi_aesebu_rx_format_put;
1748
1749
1750 if (ctl_add(card, &snd_control, asihpi) < 0)
1751 return -EINVAL;
1752
1753 asihpi_ctl_init(&snd_control, hpi_ctl, "status");
1754 snd_control.access =
1755 SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
1756 snd_control.info = snd_asihpi_aesebu_rxstatus_info;
1757 snd_control.get = snd_asihpi_aesebu_rxstatus_get;
1758
1759 return ctl_add(card, &snd_control, asihpi);
1760}
1761
1762static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol,
1763 struct snd_ctl_elem_value *ucontrol) {
1764 return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,
1765 HPI_AESEBU__transmitter_get_format);
1766}
1767
1768static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,
1769 struct snd_ctl_elem_value *ucontrol) {
1770 return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,
1771 HPI_AESEBU__transmitter_set_format);
1772}
1773
1774
1775static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
1776 struct hpi_control *hpi_ctl)
1777{
1778 struct snd_card *card = asihpi->card;
1779 struct snd_kcontrol_new snd_control;
1780
1781 asihpi_ctl_init(&snd_control, hpi_ctl, "format");
1782 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1783 snd_control.info = snd_asihpi_aesebu_format_info;
1784 snd_control.get = snd_asihpi_aesebu_tx_format_get;
1785 snd_control.put = snd_asihpi_aesebu_tx_format_put;
1786
1787 return ctl_add(card, &snd_control, asihpi);
1788}
1789
1790/*------------------------------------------------------------
1791 Tuner controls
1792 ------------------------------------------------------------*/
1793
1794/* Gain */
1795
1796static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol,
1797 struct snd_ctl_elem_info *uinfo)
1798{
1799 u32 h_control = kcontrol->private_value;
1800 u16 err;
1801 short idx;
1802 u16 gain_range[3];
1803
1804 for (idx = 0; idx < 3; idx++) {
1805 err = hpi_tuner_query_gain(ss, h_control,
1806 idx, &gain_range[idx]);
1807 if (err != 0)
1808 return err;
1809 }
1810
1811 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1812 uinfo->count = 1;
1813 uinfo->value.integer.min = ((int)gain_range[0]) / HPI_UNITS_PER_dB;
1814 uinfo->value.integer.max = ((int)gain_range[1]) / HPI_UNITS_PER_dB;
1815 uinfo->value.integer.step = ((int) gain_range[2]) / HPI_UNITS_PER_dB;
1816 return 0;
1817}
1818
1819static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol,
1820 struct snd_ctl_elem_value *ucontrol)
1821{
1822 /*
1823 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1824 */
1825 u32 h_control = kcontrol->private_value;
1826 short gain;
1827
1828 hpi_handle_error(hpi_tuner_get_gain(ss, h_control, &gain));
1829 ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB;
1830
1831 return 0;
1832}
1833
1834static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol,
1835 struct snd_ctl_elem_value *ucontrol)
1836{
1837 /*
1838 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1839 */
1840 u32 h_control = kcontrol->private_value;
1841 short gain;
1842
1843 gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;
1844 hpi_handle_error(hpi_tuner_set_gain(ss, h_control, gain));
1845
1846 return 1;
1847}
1848
1849/* Band */
1850
1851static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol,
1852 u16 *band_list, u32 len) {
1853 u32 h_control = kcontrol->private_value;
1854 u16 err = 0;
1855 u32 i;
1856
1857 for (i = 0; i < len; i++) {
1858 err = hpi_tuner_query_band(ss,
1859 h_control, i, &band_list[i]);
1860 if (err != 0)
1861 break;
1862 }
1863
1864 if (err && (err != HPI_ERROR_INVALID_OBJ_INDEX))
1865 return -EIO;
1866
1867 return i;
1868}
1869
1870static int snd_asihpi_tuner_band_info(struct snd_kcontrol *kcontrol,
1871 struct snd_ctl_elem_info *uinfo)
1872{
1873 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1874 int num_bands = 0;
1875
1876 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1877 HPI_TUNER_BAND_LAST);
1878
1879 if (num_bands < 0)
1880 return num_bands;
1881
1882 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1883 uinfo->count = 1;
1884 uinfo->value.enumerated.items = num_bands;
1885
1886 if (num_bands > 0) {
1887 if (uinfo->value.enumerated.item >=
1888 uinfo->value.enumerated.items)
1889 uinfo->value.enumerated.item =
1890 uinfo->value.enumerated.items - 1;
1891
1892 strcpy(uinfo->value.enumerated.name,
1893 asihpi_tuner_band_names[
1894 tuner_bands[uinfo->value.enumerated.item]]);
1895
1896 }
1897 return 0;
1898}
1899
1900static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol,
1901 struct snd_ctl_elem_value *ucontrol)
1902{
1903 u32 h_control = kcontrol->private_value;
1904 /*
1905 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1906 */
1907 u16 band, idx;
1908 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1909 u32 num_bands = 0;
1910
1911 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1912 HPI_TUNER_BAND_LAST);
1913
1914 hpi_handle_error(hpi_tuner_get_band(ss, h_control, &band));
1915
1916 ucontrol->value.enumerated.item[0] = -1;
1917 for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++)
1918 if (tuner_bands[idx] == band) {
1919 ucontrol->value.enumerated.item[0] = idx;
1920 break;
1921 }
1922
1923 return 0;
1924}
1925
1926static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol,
1927 struct snd_ctl_elem_value *ucontrol)
1928{
1929 /*
1930 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1931 */
1932 u32 h_control = kcontrol->private_value;
1933 u16 band;
1934 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1935 u32 num_bands = 0;
1936
1937 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1938 HPI_TUNER_BAND_LAST);
1939
1940 band = tuner_bands[ucontrol->value.enumerated.item[0]];
1941 hpi_handle_error(hpi_tuner_set_band(ss, h_control, band));
1942
1943 return 1;
1944}
1945
1946/* Freq */
1947
1948static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol,
1949 struct snd_ctl_elem_info *uinfo)
1950{
1951 u32 h_control = kcontrol->private_value;
1952 u16 err;
1953 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1954 u16 num_bands = 0, band_iter, idx;
1955 u32 freq_range[3], temp_freq_range[3];
1956
1957 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1958 HPI_TUNER_BAND_LAST);
1959
1960 freq_range[0] = INT_MAX;
1961 freq_range[1] = 0;
1962 freq_range[2] = INT_MAX;
1963
1964 for (band_iter = 0; band_iter < num_bands; band_iter++) {
1965 for (idx = 0; idx < 3; idx++) {
1966 err = hpi_tuner_query_frequency(ss, h_control,
1967 idx, tuner_bands[band_iter],
1968 &temp_freq_range[idx]);
1969 if (err != 0)
1970 return err;
1971 }
1972
1973 /* skip band with bogus stepping */
1974 if (temp_freq_range[2] <= 0)
1975 continue;
1976
1977 if (temp_freq_range[0] < freq_range[0])
1978 freq_range[0] = temp_freq_range[0];
1979 if (temp_freq_range[1] > freq_range[1])
1980 freq_range[1] = temp_freq_range[1];
1981 if (temp_freq_range[2] < freq_range[2])
1982 freq_range[2] = temp_freq_range[2];
1983 }
1984
1985 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1986 uinfo->count = 1;
1987 uinfo->value.integer.min = ((int)freq_range[0]);
1988 uinfo->value.integer.max = ((int)freq_range[1]);
1989 uinfo->value.integer.step = ((int)freq_range[2]);
1990 return 0;
1991}
1992
1993static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol,
1994 struct snd_ctl_elem_value *ucontrol)
1995{
1996 u32 h_control = kcontrol->private_value;
1997 u32 freq;
1998
1999 hpi_handle_error(hpi_tuner_get_frequency(ss, h_control, &freq));
2000 ucontrol->value.integer.value[0] = freq;
2001
2002 return 0;
2003}
2004
2005static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,
2006 struct snd_ctl_elem_value *ucontrol)
2007{
2008 u32 h_control = kcontrol->private_value;
2009 u32 freq;
2010
2011 freq = ucontrol->value.integer.value[0];
2012 hpi_handle_error(hpi_tuner_set_frequency(ss, h_control, freq));
2013
2014 return 1;
2015}
2016
2017/* Tuner control group initializer */
2018static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
2019 struct hpi_control *hpi_ctl)
2020{
2021 struct snd_card *card = asihpi->card;
2022 struct snd_kcontrol_new snd_control;
2023
2024 snd_control.private_value = hpi_ctl->h_control;
2025 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
2026
2027 if (!hpi_tuner_get_gain(ss, hpi_ctl->h_control, NULL)) {
2028 asihpi_ctl_init(&snd_control, hpi_ctl, "gain");
2029 snd_control.info = snd_asihpi_tuner_gain_info;
2030 snd_control.get = snd_asihpi_tuner_gain_get;
2031 snd_control.put = snd_asihpi_tuner_gain_put;
2032
2033 if (ctl_add(card, &snd_control, asihpi) < 0)
2034 return -EINVAL;
2035 }
2036
2037 asihpi_ctl_init(&snd_control, hpi_ctl, "band");
2038 snd_control.info = snd_asihpi_tuner_band_info;
2039 snd_control.get = snd_asihpi_tuner_band_get;
2040 snd_control.put = snd_asihpi_tuner_band_put;
2041
2042 if (ctl_add(card, &snd_control, asihpi) < 0)
2043 return -EINVAL;
2044
2045 asihpi_ctl_init(&snd_control, hpi_ctl, "freq");
2046 snd_control.info = snd_asihpi_tuner_freq_info;
2047 snd_control.get = snd_asihpi_tuner_freq_get;
2048 snd_control.put = snd_asihpi_tuner_freq_put;
2049
2050 return ctl_add(card, &snd_control, asihpi);
2051}
2052
2053/*------------------------------------------------------------
2054 Meter controls
2055 ------------------------------------------------------------*/
2056static int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol,
2057 struct snd_ctl_elem_info *uinfo)
2058{
2059 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2060 uinfo->count = HPI_MAX_CHANNELS;
2061 uinfo->value.integer.min = 0;
2062 uinfo->value.integer.max = 0x7FFFFFFF;
2063 return 0;
2064}
2065
2066/* linear values for 10dB steps */
2067static int log2lin[] = {
2068 0x7FFFFFFF, /* 0dB */
2069 679093956,
2070 214748365,
2071 67909396,
2072 21474837,
2073 6790940,
2074 2147484, /* -60dB */
2075 679094,
2076 214748, /* -80 */
2077 67909,
2078 21475, /* -100 */
2079 6791,
2080 2147,
2081 679,
2082 214,
2083 68,
2084 21,
2085 7,
2086 2
2087};
2088
2089static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,
2090 struct snd_ctl_elem_value *ucontrol)
2091{
2092 u32 h_control = kcontrol->private_value;
2093 short an_gain_mB[HPI_MAX_CHANNELS], i;
2094 u16 err;
2095
2096 err = hpi_meter_get_peak(ss, h_control, an_gain_mB);
2097
2098 for (i = 0; i < HPI_MAX_CHANNELS; i++) {
2099 if (err) {
2100 ucontrol->value.integer.value[i] = 0;
2101 } else if (an_gain_mB[i] >= 0) {
2102 ucontrol->value.integer.value[i] =
2103 an_gain_mB[i] << 16;
2104 } else {
2105 /* -ve is log value in millibels < -60dB,
2106 * convert to (roughly!) linear,
2107 */
2108 ucontrol->value.integer.value[i] =
2109 log2lin[an_gain_mB[i] / -1000];
2110 }
2111 }
2112 return 0;
2113}
2114
2115static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
2116 struct hpi_control *hpi_ctl, int subidx)
2117{
2118 struct snd_card *card = asihpi->card;
2119 struct snd_kcontrol_new snd_control;
2120
2121 asihpi_ctl_init(&snd_control, hpi_ctl, "meter");
2122 snd_control.access =
2123 SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
2124 snd_control.info = snd_asihpi_meter_info;
2125 snd_control.get = snd_asihpi_meter_get;
2126
2127 snd_control.index = subidx;
2128
2129 return ctl_add(card, &snd_control, asihpi);
2130}
2131
2132/*------------------------------------------------------------
2133 Multiplexer controls
2134 ------------------------------------------------------------*/
2135static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control)
2136{
2137 u32 h_control = snd_control->private_value;
2138 struct hpi_control hpi_ctl;
2139 int s, err;
2140 for (s = 0; s < 32; s++) {
2141 err = hpi_multiplexer_query_source(ss, h_control, s,
2142 &hpi_ctl.
2143 src_node_type,
2144 &hpi_ctl.
2145 src_node_index);
2146 if (err)
2147 break;
2148 }
2149 return s;
2150}
2151
2152static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
2153 struct snd_ctl_elem_info *uinfo)
2154{
2155 int err;
2156 u16 src_node_type, src_node_index;
2157 u32 h_control = kcontrol->private_value;
2158
2159 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2160 uinfo->count = 1;
2161 uinfo->value.enumerated.items =
2162 snd_card_asihpi_mux_count_sources(kcontrol);
2163
2164 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2165 uinfo->value.enumerated.item =
2166 uinfo->value.enumerated.items - 1;
2167
2168 err =
2169 hpi_multiplexer_query_source(ss, h_control,
2170 uinfo->value.enumerated.item,
2171 &src_node_type, &src_node_index);
2172
2173 sprintf(uinfo->value.enumerated.name, "%s %d",
2174 asihpi_src_names[src_node_type - HPI_SOURCENODE_BASE],
2175 src_node_index);
2176 return 0;
2177}
2178
2179static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol,
2180 struct snd_ctl_elem_value *ucontrol)
2181{
2182 u32 h_control = kcontrol->private_value;
2183 u16 source_type, source_index;
2184 u16 src_node_type, src_node_index;
2185 int s;
2186
2187 hpi_handle_error(hpi_multiplexer_get_source(ss, h_control,
2188 &source_type, &source_index));
2189 /* Should cache this search result! */
2190 for (s = 0; s < 256; s++) {
2191 if (hpi_multiplexer_query_source(ss, h_control, s,
2192 &src_node_type, &src_node_index))
2193 break;
2194
2195 if ((source_type == src_node_type)
2196 && (source_index == src_node_index)) {
2197 ucontrol->value.enumerated.item[0] = s;
2198 return 0;
2199 }
2200 }
2201 snd_printd(KERN_WARNING
2202 "control %x failed to match mux source %hu %hu\n",
2203 h_control, source_type, source_index);
2204 ucontrol->value.enumerated.item[0] = 0;
2205 return 0;
2206}
2207
2208static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,
2209 struct snd_ctl_elem_value *ucontrol)
2210{
2211 int change;
2212 u32 h_control = kcontrol->private_value;
2213 u16 source_type, source_index;
2214 u16 e;
2215
2216 change = 1;
2217
2218 e = hpi_multiplexer_query_source(ss, h_control,
2219 ucontrol->value.enumerated.item[0],
2220 &source_type, &source_index);
2221 if (!e)
2222 hpi_handle_error(
2223 hpi_multiplexer_set_source(ss, h_control,
2224 source_type, source_index));
2225 return change;
2226}
2227
2228
2229static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
2230 struct hpi_control *hpi_ctl)
2231{
2232 struct snd_card *card = asihpi->card;
2233 struct snd_kcontrol_new snd_control;
2234
2235#if ASI_STYLE_NAMES
2236 asihpi_ctl_init(&snd_control, hpi_ctl, "multiplexer");
2237#else
2238 asihpi_ctl_init(&snd_control, hpi_ctl, "route");
2239#endif
2240 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
2241 snd_control.info = snd_asihpi_mux_info;
2242 snd_control.get = snd_asihpi_mux_get;
2243 snd_control.put = snd_asihpi_mux_put;
2244
2245 return ctl_add(card, &snd_control, asihpi);
2246
2247}
2248
2249/*------------------------------------------------------------
2250 Channel mode controls
2251 ------------------------------------------------------------*/
2252static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol,
2253 struct snd_ctl_elem_info *uinfo)
2254{
2255 static char *mode_names[HPI_CHANNEL_MODE_LAST] = {
2256 "normal", "swap",
2257 "from_left", "from_right",
2258 "to_left", "to_right"
2259 };
2260
2261 u32 h_control = kcontrol->private_value;
2262 u16 mode;
2263 int i;
2264
2265 /* HPI channel mode values can be from 1 to 6
2266 Some adapters only support a contiguous subset
2267 */
2268 for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++)
2269 if (hpi_channel_mode_query_mode(
2270 ss, h_control, i, &mode))
2271 break;
2272
2273 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2274 uinfo->count = 1;
2275 uinfo->value.enumerated.items = i;
2276
2277 if (uinfo->value.enumerated.item >= i)
2278 uinfo->value.enumerated.item = i - 1;
2279
2280 strcpy(uinfo->value.enumerated.name,
2281 mode_names[uinfo->value.enumerated.item]);
2282
2283 return 0;
2284}
2285
2286static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol,
2287 struct snd_ctl_elem_value *ucontrol)
2288{
2289 u32 h_control = kcontrol->private_value;
2290 u16 mode;
2291
2292 if (hpi_channel_mode_get(ss, h_control, &mode))
2293 mode = 1;
2294
2295 ucontrol->value.enumerated.item[0] = mode - 1;
2296
2297 return 0;
2298}
2299
2300static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,
2301 struct snd_ctl_elem_value *ucontrol)
2302{
2303 int change;
2304 u32 h_control = kcontrol->private_value;
2305
2306 change = 1;
2307
2308 hpi_handle_error(hpi_channel_mode_set(ss, h_control,
2309 ucontrol->value.enumerated.item[0] + 1));
2310 return change;
2311}
2312
2313
2314static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
2315 struct hpi_control *hpi_ctl)
2316{
2317 struct snd_card *card = asihpi->card;
2318 struct snd_kcontrol_new snd_control;
2319
2320 asihpi_ctl_init(&snd_control, hpi_ctl, "channel mode");
2321 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
2322 snd_control.info = snd_asihpi_cmode_info;
2323 snd_control.get = snd_asihpi_cmode_get;
2324 snd_control.put = snd_asihpi_cmode_put;
2325
2326 return ctl_add(card, &snd_control, asihpi);
2327}
2328
2329/*------------------------------------------------------------
2330 Sampleclock source controls
2331 ------------------------------------------------------------*/
2332
2333static char *sampleclock_sources[MAX_CLOCKSOURCES] =
2334 { "N/A", "local PLL", "AES/EBU sync", "word external", "word header",
2335 "SMPTE", "AES/EBU in1", "auto", "network", "invalid",
2336 "prev module",
2337 "AES/EBU in2", "AES/EBU in3", "AES/EBU in4", "AES/EBU in5",
2338 "AES/EBU in6", "AES/EBU in7", "AES/EBU in8"};
2339
2340
2341
2342static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,
2343 struct snd_ctl_elem_info *uinfo)
2344{
2345 struct snd_card_asihpi *asihpi =
2346 (struct snd_card_asihpi *)(kcontrol->private_data);
2347 struct clk_cache *clkcache = &asihpi->cc;
2348 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2349 uinfo->count = 1;
2350 uinfo->value.enumerated.items = clkcache->count;
2351
2352 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2353 uinfo->value.enumerated.item =
2354 uinfo->value.enumerated.items - 1;
2355
2356 strcpy(uinfo->value.enumerated.name,
2357 clkcache->s[uinfo->value.enumerated.item].name);
2358 return 0;
2359}
2360
2361static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,
2362 struct snd_ctl_elem_value *ucontrol)
2363{
2364 struct snd_card_asihpi *asihpi =
2365 (struct snd_card_asihpi *)(kcontrol->private_data);
2366 struct clk_cache *clkcache = &asihpi->cc;
2367 u32 h_control = kcontrol->private_value;
2368 u16 source, srcindex = 0;
2369 int i;
2370
2371 ucontrol->value.enumerated.item[0] = 0;
2372 if (hpi_sample_clock_get_source(ss, h_control, &source))
2373 source = 0;
2374
2375 if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
2376 if (hpi_sample_clock_get_source_index(ss, h_control, &srcindex))
2377 srcindex = 0;
2378
2379 for (i = 0; i < clkcache->count; i++)
2380 if ((clkcache->s[i].source == source) &&
2381 (clkcache->s[i].index == srcindex))
2382 break;
2383
2384 ucontrol->value.enumerated.item[0] = i;
2385
2386 return 0;
2387}
2388
2389static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol,
2390 struct snd_ctl_elem_value *ucontrol)
2391{
2392 struct snd_card_asihpi *asihpi =
2393 (struct snd_card_asihpi *)(kcontrol->private_data);
2394 struct clk_cache *clkcache = &asihpi->cc;
2395 int change, item;
2396 u32 h_control = kcontrol->private_value;
2397
2398 change = 1;
2399 item = ucontrol->value.enumerated.item[0];
2400 if (item >= clkcache->count)
2401 item = clkcache->count-1;
2402
2403 hpi_handle_error(hpi_sample_clock_set_source(ss,
2404 h_control, clkcache->s[item].source));
2405
2406 if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
2407 hpi_handle_error(hpi_sample_clock_set_source_index(ss,
2408 h_control, clkcache->s[item].index));
2409 return change;
2410}
2411
2412/*------------------------------------------------------------
2413 Clkrate controls
2414 ------------------------------------------------------------*/
2415/* Need to change this to enumerated control with list of rates */
2416static int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol,
2417 struct snd_ctl_elem_info *uinfo)
2418{
2419 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2420 uinfo->count = 1;
2421 uinfo->value.integer.min = 8000;
2422 uinfo->value.integer.max = 192000;
2423 uinfo->value.integer.step = 100;
2424
2425 return 0;
2426}
2427
2428static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol,
2429 struct snd_ctl_elem_value *ucontrol)
2430{
2431 u32 h_control = kcontrol->private_value;
2432 u32 rate;
2433 u16 e;
2434
2435 e = hpi_sample_clock_get_local_rate(ss, h_control, &rate);
2436 if (!e)
2437 ucontrol->value.integer.value[0] = rate;
2438 else
2439 ucontrol->value.integer.value[0] = 0;
2440 return 0;
2441}
2442
2443static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol,
2444 struct snd_ctl_elem_value *ucontrol)
2445{
2446 int change;
2447 u32 h_control = kcontrol->private_value;
2448
2449 /* change = asihpi->mixer_clkrate[addr][0] != left ||
2450 asihpi->mixer_clkrate[addr][1] != right;
2451 */
2452 change = 1;
2453 hpi_handle_error(hpi_sample_clock_set_local_rate(ss, h_control,
2454 ucontrol->value.integer.value[0]));
2455 return change;
2456}
2457
2458static int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol,
2459 struct snd_ctl_elem_info *uinfo)
2460{
2461 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2462 uinfo->count = 1;
2463 uinfo->value.integer.min = 8000;
2464 uinfo->value.integer.max = 192000;
2465 uinfo->value.integer.step = 100;
2466
2467 return 0;
2468}
2469
2470static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
2471 struct snd_ctl_elem_value *ucontrol)
2472{
2473 u32 h_control = kcontrol->private_value;
2474 u32 rate;
2475 u16 e;
2476
2477 e = hpi_sample_clock_get_sample_rate(ss, h_control, &rate);
2478 if (!e)
2479 ucontrol->value.integer.value[0] = rate;
2480 else
2481 ucontrol->value.integer.value[0] = 0;
2482 return 0;
2483}
2484
2485static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
2486 struct hpi_control *hpi_ctl)
2487{
2488 struct snd_card *card = asihpi->card;
2489 struct snd_kcontrol_new snd_control;
2490
2491 struct clk_cache *clkcache = &asihpi->cc;
2492 u32 hSC = hpi_ctl->h_control;
2493 int has_aes_in = 0;
2494 int i, j;
2495 u16 source;
2496
2497 snd_control.private_value = hpi_ctl->h_control;
2498
2499 clkcache->has_local = 0;
2500
2501 for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) {
2502 if (hpi_sample_clock_query_source(ss, hSC,
2503 i, &source))
2504 break;
2505 clkcache->s[i].source = source;
2506 clkcache->s[i].index = 0;
2507 clkcache->s[i].name = sampleclock_sources[source];
2508 if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
2509 has_aes_in = 1;
2510 if (source == HPI_SAMPLECLOCK_SOURCE_LOCAL)
2511 clkcache->has_local = 1;
2512 }
2513 if (has_aes_in)
2514 /* already will have picked up index 0 above */
2515 for (j = 1; j < 8; j++) {
2516 if (hpi_sample_clock_query_source_index(ss, hSC,
2517 j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT,
2518 &source))
2519 break;
2520 clkcache->s[i].source =
2521 HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT;
2522 clkcache->s[i].index = j;
2523 clkcache->s[i].name = sampleclock_sources[
2524 j+HPI_SAMPLECLOCK_SOURCE_LAST];
2525 i++;
2526 }
2527 clkcache->count = i;
2528
2529 asihpi_ctl_init(&snd_control, hpi_ctl, "source");
2530 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
2531 snd_control.info = snd_asihpi_clksrc_info;
2532 snd_control.get = snd_asihpi_clksrc_get;
2533 snd_control.put = snd_asihpi_clksrc_put;
2534 if (ctl_add(card, &snd_control, asihpi) < 0)
2535 return -EINVAL;
2536
2537
2538 if (clkcache->has_local) {
2539 asihpi_ctl_init(&snd_control, hpi_ctl, "local_rate");
2540 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
2541 snd_control.info = snd_asihpi_clklocal_info;
2542 snd_control.get = snd_asihpi_clklocal_get;
2543 snd_control.put = snd_asihpi_clklocal_put;
2544
2545
2546 if (ctl_add(card, &snd_control, asihpi) < 0)
2547 return -EINVAL;
2548 }
2549
2550 asihpi_ctl_init(&snd_control, hpi_ctl, "rate");
2551 snd_control.access =
2552 SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
2553 snd_control.info = snd_asihpi_clkrate_info;
2554 snd_control.get = snd_asihpi_clkrate_get;
2555
2556 return ctl_add(card, &snd_control, asihpi);
2557}
2558/*------------------------------------------------------------
2559 Mixer
2560 ------------------------------------------------------------*/
2561
2562static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
2563{
2564 struct snd_card *card = asihpi->card;
2565 unsigned int idx = 0;
2566 unsigned int subindex = 0;
2567 int err;
2568 struct hpi_control hpi_ctl, prev_ctl;
2569
2570 if (snd_BUG_ON(!asihpi))
2571 return -EINVAL;
2572 strcpy(card->mixername, "asihpi mixer");
2573
2574 err =
2575 hpi_mixer_open(ss, asihpi->adapter_index,
2576 &asihpi->h_mixer);
2577 hpi_handle_error(err);
2578 if (err)
2579 return -err;
2580
2581 for (idx = 0; idx < 2000; idx++) {
2582 err = hpi_mixer_get_control_by_index(
2583 ss, asihpi->h_mixer,
2584 idx,
2585 &hpi_ctl.src_node_type,
2586 &hpi_ctl.src_node_index,
2587 &hpi_ctl.dst_node_type,
2588 &hpi_ctl.dst_node_index,
2589 &hpi_ctl.control_type,
2590 &hpi_ctl.h_control);
2591 if (err) {
2592 if (err == HPI_ERROR_CONTROL_DISABLED) {
2593 if (mixer_dump)
2594 snd_printk(KERN_INFO
2595 "disabled HPI control(%d)\n",
2596 idx);
2597 continue;
2598 } else
2599 break;
2600
2601 }
2602
2603 hpi_ctl.src_node_type -= HPI_SOURCENODE_BASE;
2604 hpi_ctl.dst_node_type -= HPI_DESTNODE_BASE;
2605
2606 /* ASI50xx in SSX mode has multiple meters on the same node.
2607 Use subindex to create distinct ALSA controls
2608 for any duplicated controls.
2609 */
2610 if ((hpi_ctl.control_type == prev_ctl.control_type) &&
2611 (hpi_ctl.src_node_type == prev_ctl.src_node_type) &&
2612 (hpi_ctl.src_node_index == prev_ctl.src_node_index) &&
2613 (hpi_ctl.dst_node_type == prev_ctl.dst_node_type) &&
2614 (hpi_ctl.dst_node_index == prev_ctl.dst_node_index))
2615 subindex++;
2616 else
2617 subindex = 0;
2618
2619 prev_ctl = hpi_ctl;
2620
2621 switch (hpi_ctl.control_type) {
2622 case HPI_CONTROL_VOLUME:
2623 err = snd_asihpi_volume_add(asihpi, &hpi_ctl);
2624 break;
2625 case HPI_CONTROL_LEVEL:
2626 err = snd_asihpi_level_add(asihpi, &hpi_ctl);
2627 break;
2628 case HPI_CONTROL_MULTIPLEXER:
2629 err = snd_asihpi_mux_add(asihpi, &hpi_ctl);
2630 break;
2631 case HPI_CONTROL_CHANNEL_MODE:
2632 err = snd_asihpi_cmode_add(asihpi, &hpi_ctl);
2633 break;
2634 case HPI_CONTROL_METER:
2635 err = snd_asihpi_meter_add(asihpi, &hpi_ctl, subindex);
2636 break;
2637 case HPI_CONTROL_SAMPLECLOCK:
2638 err = snd_asihpi_sampleclock_add(
2639 asihpi, &hpi_ctl);
2640 break;
2641 case HPI_CONTROL_CONNECTION: /* ignore these */
2642 continue;
2643 case HPI_CONTROL_TUNER:
2644 err = snd_asihpi_tuner_add(asihpi, &hpi_ctl);
2645 break;
2646 case HPI_CONTROL_AESEBU_TRANSMITTER:
2647 err = snd_asihpi_aesebu_tx_add(asihpi, &hpi_ctl);
2648 break;
2649 case HPI_CONTROL_AESEBU_RECEIVER:
2650 err = snd_asihpi_aesebu_rx_add(asihpi, &hpi_ctl);
2651 break;
2652 case HPI_CONTROL_VOX:
2653 case HPI_CONTROL_BITSTREAM:
2654 case HPI_CONTROL_MICROPHONE:
2655 case HPI_CONTROL_PARAMETRIC_EQ:
2656 case HPI_CONTROL_COMPANDER:
2657 default:
2658 if (mixer_dump)
2659 snd_printk(KERN_INFO
2660 "untranslated HPI control"
2661 "(%d) %d %d %d %d %d\n",
2662 idx,
2663 hpi_ctl.control_type,
2664 hpi_ctl.src_node_type,
2665 hpi_ctl.src_node_index,
2666 hpi_ctl.dst_node_type,
2667 hpi_ctl.dst_node_index);
2668 continue;
2669 };
2670 if (err < 0)
2671 return err;
2672 }
2673 if (HPI_ERROR_INVALID_OBJ_INDEX != err)
2674 hpi_handle_error(err);
2675
2676 snd_printk(KERN_INFO "%d mixer controls found\n", idx);
2677
2678 return 0;
2679}
2680
2681/*------------------------------------------------------------
2682 /proc interface
2683 ------------------------------------------------------------*/
2684
2685static void
2686snd_asihpi_proc_read(struct snd_info_entry *entry,
2687 struct snd_info_buffer *buffer)
2688{
2689 struct snd_card_asihpi *asihpi = entry->private_data;
2690 u16 version;
2691 u32 h_control;
2692 u32 rate = 0;
2693 u16 source = 0;
2694 int err;
2695
2696 snd_iprintf(buffer, "ASIHPI driver proc file\n");
2697 snd_iprintf(buffer,
2698 "adapter ID=%4X\n_index=%d\n"
2699 "num_outstreams=%d\n_num_instreams=%d\n",
2700 asihpi->type, asihpi->adapter_index,
2701 asihpi->num_outstreams, asihpi->num_instreams);
2702
2703 version = asihpi->version;
2704 snd_iprintf(buffer,
2705 "serial#=%d\n_hw version %c%d\nDSP code version %03d\n",
2706 asihpi->serial_number, ((version >> 3) & 0xf) + 'A',
2707 version & 0x7,
2708 ((version >> 13) * 100) + ((version >> 7) & 0x3f));
2709
2710 err = hpi_mixer_get_control(ss, asihpi->h_mixer,
2711 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
2712 HPI_CONTROL_SAMPLECLOCK, &h_control);
2713
2714 if (!err) {
2715 err = hpi_sample_clock_get_sample_rate(ss,
2716 h_control, &rate);
2717 err += hpi_sample_clock_get_source(ss, h_control, &source);
2718
2719 if (!err)
2720 snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n",
2721 rate, sampleclock_sources[source]);
2722 }
2723
2724}
2725
2726
2727static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
2728{
2729 struct snd_info_entry *entry;
2730
2731 if (!snd_card_proc_new(asihpi->card, "info", &entry))
2732 snd_info_set_text_ops(entry, asihpi, snd_asihpi_proc_read);
2733}
2734
2735/*------------------------------------------------------------
2736 HWDEP
2737 ------------------------------------------------------------*/
2738
2739static int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file)
2740{
2741 if (enable_hpi_hwdep)
2742 return 0;
2743 else
2744 return -ENODEV;
2745
2746}
2747
2748static int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file)
2749{
2750 if (enable_hpi_hwdep)
2751 return asihpi_hpi_release(file);
2752 else
2753 return -ENODEV;
2754}
2755
2756static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,
2757 unsigned int cmd, unsigned long arg)
2758{
2759 if (enable_hpi_hwdep)
2760 return asihpi_hpi_ioctl(file, cmd, arg);
2761 else
2762 return -ENODEV;
2763}
2764
2765
2766/* results in /dev/snd/hwC#D0 file for each card with index #
2767 also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
2768*/
2769static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
2770 int device, struct snd_hwdep **rhwdep)
2771{
2772 struct snd_hwdep *hw;
2773 int err;
2774
2775 if (rhwdep)
2776 *rhwdep = NULL;
2777 err = snd_hwdep_new(asihpi->card, "HPI", device, &hw);
2778 if (err < 0)
2779 return err;
2780 strcpy(hw->name, "asihpi (HPI)");
2781 hw->iface = SNDRV_HWDEP_IFACE_LAST;
2782 hw->ops.open = snd_asihpi_hpi_open;
2783 hw->ops.ioctl = snd_asihpi_hpi_ioctl;
2784 hw->ops.release = snd_asihpi_hpi_release;
2785 hw->private_data = asihpi;
2786 if (rhwdep)
2787 *rhwdep = hw;
2788 return 0;
2789}
2790
2791/*------------------------------------------------------------
2792 CARD
2793 ------------------------------------------------------------*/
2794static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
2795 const struct pci_device_id *pci_id)
2796{
2797 int err;
2798
2799 u16 version;
2800 int pcm_substreams;
2801
2802 struct hpi_adapter *hpi_card;
2803 struct snd_card *card;
2804 struct snd_card_asihpi *asihpi;
2805
2806 u32 h_control;
2807 u32 h_stream;
2808
2809 static int dev;
2810 if (dev >= SNDRV_CARDS)
2811 return -ENODEV;
2812
2813 /* Should this be enable[hpi_card->index] ? */
2814 if (!enable[dev]) {
2815 dev++;
2816 return -ENOENT;
2817 }
2818
2819 err = asihpi_adapter_probe(pci_dev, pci_id);
2820 if (err < 0)
2821 return err;
2822
2823 hpi_card = pci_get_drvdata(pci_dev);
2824 /* first try to give the card the same index as its hardware index */
2825 err = snd_card_create(hpi_card->index,
2826 id[hpi_card->index], THIS_MODULE,
2827 sizeof(struct snd_card_asihpi),
2828 &card);
2829 if (err < 0) {
2830 /* if that fails, try the default index==next available */
2831 err =
2832 snd_card_create(index[dev], id[dev],
2833 THIS_MODULE,
2834 sizeof(struct snd_card_asihpi),
2835 &card);
2836 if (err < 0)
2837 return err;
2838 snd_printk(KERN_WARNING
2839 "**** WARNING **** adapter index %d->ALSA index %d\n",
2840 hpi_card->index, card->number);
2841 }
2842
2843 asihpi = (struct snd_card_asihpi *) card->private_data;
2844 asihpi->card = card;
2845 asihpi->pci = hpi_card->pci;
2846 asihpi->adapter_index = hpi_card->index;
2847 hpi_handle_error(hpi_adapter_get_info(ss,
2848 asihpi->adapter_index,
2849 &asihpi->num_outstreams,
2850 &asihpi->num_instreams,
2851 &asihpi->version,
2852 &asihpi->serial_number, &asihpi->type));
2853
2854 version = asihpi->version;
2855 snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d "
2856 "num_instreams=%d S/N=%d\n"
2857 "hw version %c%d DSP code version %03d\n",
2858 asihpi->type, asihpi->adapter_index,
2859 asihpi->num_outstreams,
2860 asihpi->num_instreams, asihpi->serial_number,
2861 ((version >> 3) & 0xf) + 'A',
2862 version & 0x7,
2863 ((version >> 13) * 100) + ((version >> 7) & 0x3f));
2864
2865 pcm_substreams = asihpi->num_outstreams;
2866 if (pcm_substreams < asihpi->num_instreams)
2867 pcm_substreams = asihpi->num_instreams;
2868
2869 err = hpi_adapter_get_property(ss, asihpi->adapter_index,
2870 HPI_ADAPTER_PROPERTY_CAPS1,
2871 NULL, &asihpi->support_grouping);
2872 if (err)
2873 asihpi->support_grouping = 0;
2874
2875 err = hpi_adapter_get_property(ss, asihpi->adapter_index,
2876 HPI_ADAPTER_PROPERTY_CAPS2,
2877 &asihpi->support_mrx, NULL);
2878 if (err)
2879 asihpi->support_mrx = 0;
2880
2881 err = hpi_adapter_get_property(ss, asihpi->adapter_index,
2882 HPI_ADAPTER_PROPERTY_INTERVAL,
2883 NULL, &asihpi->update_interval_frames);
2884 if (err)
2885 asihpi->update_interval_frames = 512;
2886
2887 hpi_handle_error(hpi_instream_open(ss, asihpi->adapter_index,
2888 0, &h_stream));
2889
2890 err = hpi_instream_host_buffer_free(ss, h_stream);
2891 asihpi->support_mmap = (!err);
2892
2893 hpi_handle_error(hpi_instream_close(ss, h_stream));
2894
2895 err = hpi_adapter_get_property(ss, asihpi->adapter_index,
2896 HPI_ADAPTER_PROPERTY_CURCHANNELS,
2897 &asihpi->in_max_chans, &asihpi->out_max_chans);
2898 if (err) {
2899 asihpi->in_max_chans = 2;
2900 asihpi->out_max_chans = 2;
2901 }
2902
2903 snd_printk(KERN_INFO "supports mmap:%d grouping:%d mrx:%d\n",
2904 asihpi->support_mmap,
2905 asihpi->support_grouping,
2906 asihpi->support_mrx
2907 );
2908
2909
2910 err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams);
2911 if (err < 0) {
2912 snd_printk(KERN_ERR "pcm_new failed\n");
2913 goto __nodev;
2914 }
2915 err = snd_card_asihpi_mixer_new(asihpi);
2916 if (err < 0) {
2917 snd_printk(KERN_ERR "mixer_new failed\n");
2918 goto __nodev;
2919 }
2920
2921 err = hpi_mixer_get_control(ss, asihpi->h_mixer,
2922 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
2923 HPI_CONTROL_SAMPLECLOCK, &h_control);
2924
2925 if (!err)
2926 err = hpi_sample_clock_set_local_rate(
2927 ss, h_control, adapter_fs);
2928
2929 snd_asihpi_proc_init(asihpi);
2930
2931 /* always create, can be enabled or disabled dynamically
2932 by enable_hwdep module param*/
2933 snd_asihpi_hpi_new(asihpi, 0, NULL);
2934
2935 if (asihpi->support_mmap)
2936 strcpy(card->driver, "ASIHPI-MMAP");
2937 else
2938 strcpy(card->driver, "ASIHPI");
2939
2940 sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type);
2941 sprintf(card->longname, "%s %i",
2942 card->shortname, asihpi->adapter_index);
2943 err = snd_card_register(card);
2944 if (!err) {
2945 hpi_card->snd_card_asihpi = card;
2946 dev++;
2947 return 0;
2948 }
2949__nodev:
2950 snd_card_free(card);
2951 snd_printk(KERN_ERR "snd_asihpi_probe error %d\n", err);
2952 return err;
2953
2954}
2955
2956static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
2957{
2958 struct hpi_adapter *hpi_card = pci_get_drvdata(pci_dev);
2959
2960 snd_card_free(hpi_card->snd_card_asihpi);
2961 hpi_card->snd_card_asihpi = NULL;
2962 asihpi_adapter_remove(pci_dev);
2963}
2964
2965static DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = {
2966 {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
2967 HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
2968 (kernel_ulong_t)HPI_6205},
2969 {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
2970 HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
2971 (kernel_ulong_t)HPI_6000},
2972 {0,}
2973};
2974MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl);
2975
2976static struct pci_driver driver = {
2977 .name = "asihpi",
2978 .id_table = asihpi_pci_tbl,
2979 .probe = snd_asihpi_probe,
2980 .remove = __devexit_p(snd_asihpi_remove),
2981#ifdef CONFIG_PM
2982/* .suspend = snd_asihpi_suspend,
2983 .resume = snd_asihpi_resume, */
2984#endif
2985};
2986
2987static int __init snd_asihpi_init(void)
2988{
2989 asihpi_init();
2990 return pci_register_driver(&driver);
2991}
2992
2993static void __exit snd_asihpi_exit(void)
2994{
2995
2996 pci_unregister_driver(&driver);
2997 asihpi_exit();
2998}
2999
3000module_init(snd_asihpi_init)
3001module_exit(snd_asihpi_exit)
3002
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h
new file mode 100644
index 000000000000..99400de6c075
--- /dev/null
+++ b/sound/pci/asihpi/hpi.h
@@ -0,0 +1,2001 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19*/
20/** \file hpi.h
21
22 AudioScience Hardware Programming Interface (HPI)
23 public API definition.
24
25 The HPI is a low-level hardware abstraction layer to all
26 AudioScience digital audio adapters
27*/
28/*
29 You must define one operating system that the HPI is to be compiled under
30 HPI_OS_WIN32_USER 32bit Windows
31 HPI_OS_DSP_C6000 DSP TI C6000 (automatically set)
32 HPI_OS_WDM Windows WDM kernel driver
33 HPI_OS_LINUX Linux userspace
34 HPI_OS_LINUX_KERNEL Linux kernel (automatically set)
35
36(C) Copyright AudioScience Inc. 1998-2010
37******************************************************************************/
38#ifndef _HPI_H_
39#define _HPI_H_
40/* HPI Version
41If HPI_VER_MINOR is odd then its a development release not intended for the
42public. If HPI_VER_MINOR is even then is a release version
43i.e 3.05.02 is a development version
44*/
45#define HPI_VERSION_CONSTRUCTOR(maj, min, rel) \
46 ((maj << 16) + (min << 8) + rel)
47
48#define HPI_VER_MAJOR(v) ((int)(v >> 16))
49#define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF))
50#define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
51
52/* Use single digits for versions less that 10 to avoid octal. */
53#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 3, 18)
54
55/* Library version as documented in hpi-api-versions.txt */
56#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0)
57
58#include <linux/types.h>
59#define HPI_EXCLUDE_DEPRECATED
60
61/******************************************************************************/
62/******************************************************************************/
63/******** HPI API DEFINITIONS *****/
64/******************************************************************************/
65/******************************************************************************/
66/*******************************************/
67/** Audio format types
68\ingroup stream
69*/
70enum HPI_FORMATS {
71/** Used internally on adapter. */
72 HPI_FORMAT_MIXER_NATIVE = 0,
73/** 8-bit unsigned PCM. Windows equivalent is WAVE_FORMAT_PCM. */
74 HPI_FORMAT_PCM8_UNSIGNED = 1,
75/** 16-bit signed PCM. Windows equivalent is WAVE_FORMAT_PCM. */
76 HPI_FORMAT_PCM16_SIGNED = 2,
77/** MPEG-1 Layer-1. */
78 HPI_FORMAT_MPEG_L1 = 3,
79/** MPEG-1 Layer-2.
80
81Windows equivalent is WAVE_FORMAT_MPEG.
82
83The following table shows what combinations of mode and bitrate are possible:
84
85<table border=1 cellspacing=0 cellpadding=5>
86<tr>
87<td><p><b>Bitrate (kbs)</b></p>
88<td><p><b>Mono</b></p>
89<td><p><b>Stereo,<br>Joint Stereo or<br>Dual Channel</b></p>
90
91<tr><td>32<td>X<td>_
92<tr><td>40<td>_<td>_
93<tr><td>48<td>X<td>_
94<tr><td>56<td>X<td>_
95<tr><td>64<td>X<td>X
96<tr><td>80<td>X<td>_
97<tr><td>96<td>X<td>X
98<tr><td>112<td>X<td>X
99<tr><td>128<td>X<td>X
100<tr><td>160<td>X<td>X
101<tr><td>192<td>X<td>X
102<tr><td>224<td>_<td>X
103<tr><td>256<td>-<td>X
104<tr><td>320<td>-<td>X
105<tr><td>384<td>_<td>X
106</table>
107*/
108 HPI_FORMAT_MPEG_L2 = 4,
109/** MPEG-1 Layer-3.
110Windows equivalent is WAVE_FORMAT_MPEG.
111
112The following table shows what combinations of mode and bitrate are possible:
113
114<table border=1 cellspacing=0 cellpadding=5>
115<tr>
116<td><p><b>Bitrate (kbs)</b></p>
117<td><p><b>Mono<br>Stereo @ 8,<br>11.025 and<br>12kHz*</b></p>
118<td><p><b>Mono<br>Stereo @ 16,<br>22.050 and<br>24kHz*</b></p>
119<td><p><b>Mono<br>Stereo @ 32,<br>44.1 and<br>48kHz</b></p>
120
121<tr><td>16<td>X<td>X<td>_
122<tr><td>24<td>X<td>X<td>_
123<tr><td>32<td>X<td>X<td>X
124<tr><td>40<td>X<td>X<td>X
125<tr><td>48<td>X<td>X<td>X
126<tr><td>56<td>X<td>X<td>X
127<tr><td>64<td>X<td>X<td>X
128<tr><td>80<td>_<td>X<td>X
129<tr><td>96<td>_<td>X<td>X
130<tr><td>112<td>_<td>X<td>X
131<tr><td>128<td>_<td>X<td>X
132<tr><td>144<td>_<td>X<td>_
133<tr><td>160<td>_<td>X<td>X
134<tr><td>192<td>_<td>_<td>X
135<tr><td>224<td>_<td>_<td>X
136<tr><td>256<td>-<td>_<td>X
137<tr><td>320<td>-<td>_<td>X
138</table>
139\b * Available on the ASI6000 series only
140*/
141 HPI_FORMAT_MPEG_L3 = 5,
142/** Dolby AC-2. */
143 HPI_FORMAT_DOLBY_AC2 = 6,
144/** Dolbt AC-3. */
145 HPI_FORMAT_DOLBY_AC3 = 7,
146/** 16-bit PCM big-endian. */
147 HPI_FORMAT_PCM16_BIGENDIAN = 8,
148/** TAGIT-1 algorithm - hits. */
149 HPI_FORMAT_AA_TAGIT1_HITS = 9,
150/** TAGIT-1 algorithm - inserts. */
151 HPI_FORMAT_AA_TAGIT1_INSERTS = 10,
152/** 32-bit signed PCM. Windows equivalent is WAVE_FORMAT_PCM.
153Each sample is a 32bit word. The most significant 24 bits contain a 24-bit
154sample and the least significant 8 bits are set to 0.
155*/
156 HPI_FORMAT_PCM32_SIGNED = 11,
157/** Raw bitstream - unknown format. */
158 HPI_FORMAT_RAW_BITSTREAM = 12,
159/** TAGIT-1 algorithm hits - extended. */
160 HPI_FORMAT_AA_TAGIT1_HITS_EX1 = 13,
161/** 32-bit PCM as an IEEE float. Windows equivalent is WAVE_FORMAT_IEEE_FLOAT.
162Each sample is a 32bit word in IEEE754 floating point format.
163The range is +1.0 to -1.0, which corresponds to digital fullscale.
164*/
165 HPI_FORMAT_PCM32_FLOAT = 14,
166/** 24-bit PCM signed. Windows equivalent is WAVE_FORMAT_PCM. */
167 HPI_FORMAT_PCM24_SIGNED = 15,
168/** OEM format 1 - private. */
169 HPI_FORMAT_OEM1 = 16,
170/** OEM format 2 - private. */
171 HPI_FORMAT_OEM2 = 17,
172/** Undefined format. */
173 HPI_FORMAT_UNDEFINED = 0xffff
174};
175
176/******************************************* in/out Stream states */
177/*******************************************/
178/** Stream States
179\ingroup stream
180*/
181enum HPI_STREAM_STATES {
182 /** State stopped - stream is stopped. */
183 HPI_STATE_STOPPED = 1,
184 /** State playing - stream is playing audio. */
185 HPI_STATE_PLAYING = 2,
186 /** State recording - stream is recording. */
187 HPI_STATE_RECORDING = 3,
188 /** State drained - playing stream ran out of data to play. */
189 HPI_STATE_DRAINED = 4,
190 /** State generate sine - to be implemented. */
191 HPI_STATE_SINEGEN = 5,
192 /** State wait - used for inter-card sync to mean waiting for all
193 cards to be ready. */
194 HPI_STATE_WAIT = 6
195};
196/******************************************* mixer source node types */
197/** Source node types
198\ingroup mixer
199*/
200enum HPI_SOURCENODES {
201 /** This define can be used instead of 0 to indicate
202 that there is no valid source node. A control that
203 exists on a destination node can be searched for using a source
204 node value of either 0, or HPI_SOURCENODE_NONE */
205 HPI_SOURCENODE_NONE = 100,
206 /** \deprecated Use HPI_SOURCENODE_NONE instead. */
207 HPI_SOURCENODE_BASE = 100,
208 /** Out Stream (Play) node. */
209 HPI_SOURCENODE_OSTREAM = 101,
210 /** Line in node - could be analog, AES/EBU or network. */
211 HPI_SOURCENODE_LINEIN = 102,
212 HPI_SOURCENODE_AESEBU_IN = 103, /**< AES/EBU input node. */
213 HPI_SOURCENODE_TUNER = 104, /**< tuner node. */
214 HPI_SOURCENODE_RF = 105, /**< RF input node. */
215 HPI_SOURCENODE_CLOCK_SOURCE = 106, /**< clock source node. */
216 HPI_SOURCENODE_RAW_BITSTREAM = 107, /**< raw bitstream node. */
217 HPI_SOURCENODE_MICROPHONE = 108, /**< microphone node. */
218 /** Cobranet input node -
219 Audio samples come from the Cobranet network and into the device. */
220 HPI_SOURCENODE_COBRANET = 109,
221 HPI_SOURCENODE_ANALOG = 110, /**< analog input node. */
222 HPI_SOURCENODE_ADAPTER = 111, /**< adapter node. */
223 /* !!!Update this AND hpidebug.h if you add a new sourcenode type!!! */
224 HPI_SOURCENODE_LAST_INDEX = 111 /**< largest ID */
225 /* AX6 max sourcenode types = 15 */
226};
227
228/******************************************* mixer dest node types */
229/** Destination node types
230\ingroup mixer
231*/
232enum HPI_DESTNODES {
233 /** This define can be used instead of 0 to indicate
234 that there is no valid destination node. A control that
235 exists on a source node can be searched for using a destination
236 node value of either 0, or HPI_DESTNODE_NONE */
237 HPI_DESTNODE_NONE = 200,
238 /** \deprecated Use HPI_DESTNODE_NONE instead. */
239 HPI_DESTNODE_BASE = 200,
240 /** In Stream (Record) node. */
241 HPI_DESTNODE_ISTREAM = 201,
242 HPI_DESTNODE_LINEOUT = 202, /**< line out node. */
243 HPI_DESTNODE_AESEBU_OUT = 203, /**< AES/EBU output node. */
244 HPI_DESTNODE_RF = 204, /**< RF output node. */
245 HPI_DESTNODE_SPEAKER = 205, /**< speaker output node. */
246 /** Cobranet output node -
247 Audio samples from the device are sent out on the Cobranet network.*/
248 HPI_DESTNODE_COBRANET = 206,
249 HPI_DESTNODE_ANALOG = 207, /**< analog output node. */
250
251 /* !!!Update this AND hpidebug.h if you add a new destnode type!!! */
252 HPI_DESTNODE_LAST_INDEX = 207 /**< largest ID */
253 /* AX6 max destnode types = 15 */
254};
255
256/*******************************************/
257/** Mixer control types
258\ingroup mixer
259*/
260enum HPI_CONTROLS {
261 HPI_CONTROL_GENERIC = 0, /**< generic control. */
262 HPI_CONTROL_CONNECTION = 1, /**< A connection between nodes. */
263 HPI_CONTROL_VOLUME = 2, /**< volume control - works in dB_fs. */
264 HPI_CONTROL_METER = 3, /**< peak meter control. */
265 HPI_CONTROL_MUTE = 4, /*mute control - not used at present. */
266 HPI_CONTROL_MULTIPLEXER = 5, /**< multiplexer control. */
267
268 HPI_CONTROL_AESEBU_TRANSMITTER = 6, /**< AES/EBU transmitter control. */
269 HPI_CONTROL_AESEBUTX = HPI_CONTROL_AESEBU_TRANSMITTER,
270
271 HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */
272 HPI_CONTROL_AESEBURX = HPI_CONTROL_AESEBU_RECEIVER,
273
274 HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */
275 HPI_CONTROL_TUNER = 9, /**< tuner control. */
276/* HPI_CONTROL_ONOFFSWITCH = 10 */
277 HPI_CONTROL_VOX = 11, /**< vox control. */
278/* HPI_CONTROL_AES18_TRANSMITTER = 12 */
279/* HPI_CONTROL_AES18_RECEIVER = 13 */
280/* HPI_CONTROL_AES18_BLOCKGENERATOR = 14 */
281 HPI_CONTROL_CHANNEL_MODE = 15, /**< channel mode control. */
282
283 HPI_CONTROL_BITSTREAM = 16, /**< bitstream control. */
284 HPI_CONTROL_SAMPLECLOCK = 17, /**< sample clock control. */
285 HPI_CONTROL_MICROPHONE = 18, /**< microphone control. */
286 HPI_CONTROL_PARAMETRIC_EQ = 19, /**< parametric EQ control. */
287 HPI_CONTROL_EQUALIZER = HPI_CONTROL_PARAMETRIC_EQ,
288
289 HPI_CONTROL_COMPANDER = 20, /**< compander control. */
290 HPI_CONTROL_COBRANET = 21, /**< cobranet control. */
291 HPI_CONTROL_TONEDETECTOR = 22, /**< tone detector control. */
292 HPI_CONTROL_SILENCEDETECTOR = 23, /**< silence detector control. */
293 HPI_CONTROL_PAD = 24, /**< tuner PAD control. */
294 HPI_CONTROL_SRC = 25, /**< samplerate converter control. */
295 HPI_CONTROL_UNIVERSAL = 26, /**< universal control. */
296
297/* !!! Update this AND hpidebug.h if you add a new control type!!!*/
298 HPI_CONTROL_LAST_INDEX = 26 /**<highest control type ID */
299/* WARNING types 256 or greater impact bit packing in all AX6 DSP code */
300};
301
302/* Shorthand names that match attribute names */
303
304/******************************************* ADAPTER ATTRIBUTES ****/
305
306/** Adapter properties
307These are used in HPI_AdapterSetProperty() and HPI_AdapterGetProperty()
308\ingroup adapter
309*/
310enum HPI_ADAPTER_PROPERTIES {
311/** \internal Used in dwProperty field of HPI_AdapterSetProperty() and
312HPI_AdapterGetProperty(). This errata applies to all ASI6000 cards with both
313analog and digital outputs. The CS4224 A/D+D/A has a one sample delay between
314left and right channels on both its input (ADC) and output (DAC).
315More details are available in Cirrus Logic errata ER284B2.
316PDF available from www.cirrus.com, released by Cirrus in 2001.
317*/
318 HPI_ADAPTER_PROPERTY_ERRATA_1 = 1,
319
320/** Adapter grouping property
321Indicates whether the adapter supports the grouping API (for ASIO and SSX2)
322*/
323 HPI_ADAPTER_PROPERTY_GROUPING = 2,
324
325/** Driver SSX2 property
326Tells the kernel driver to turn on SSX2 stream mapping.
327This feature is not used by the DSP. In fact the call is completely processed
328by the driver and is not passed on to the DSP at all.
329*/
330 HPI_ADAPTER_PROPERTY_ENABLE_SSX2 = 3,
331
332/** Adapter SSX2 property
333Indicates the state of the adapter's SSX2 setting. This setting is stored in
334non-volatile memory on the adapter. A typical call sequence would be to use
335HPI_ADAPTER_PROPERTY_SSX2_SETTING to set SSX2 on the adapter and then to reload
336the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during startup
337and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2 to enable
338SSX2 stream mapping within the kernel level of the driver.
339*/
340 HPI_ADAPTER_PROPERTY_SSX2_SETTING = 4,
341
342/** Base number for readonly properties */
343 HPI_ADAPTER_PROPERTY_READONLYBASE = 256,
344
345/** Readonly adapter latency property.
346This property returns in the input and output latency in samples.
347Property 1 is the estimated input latency
348in samples, while Property 2 is that output latency in samples.
349*/
350 HPI_ADAPTER_PROPERTY_LATENCY = 256,
351
352/** Readonly adapter granularity property.
353The granulariy is the smallest size chunk of stereo samples that is processed by
354the adapter.
355This property returns the record granularity in samples in Property 1.
356Property 2 returns the play granularity.
357*/
358 HPI_ADAPTER_PROPERTY_GRANULARITY = 257,
359
360/** Readonly adapter number of current channels property.
361Property 1 is the number of record channels per record device.
362Property 2 is the number of play channels per playback device.*/
363 HPI_ADAPTER_PROPERTY_CURCHANNELS = 258,
364
365/** Readonly adapter software version.
366The SOFTWARE_VERSION property returns the version of the software running
367on the adapter as Major.Minor.Release.
368Property 1 contains Major in bits 15..8 and Minor in bits 7..0.
369Property 2 contains Release in bits 7..0. */
370 HPI_ADAPTER_PROPERTY_SOFTWARE_VERSION = 259,
371
372/** Readonly adapter MAC address MSBs.
373The MAC_ADDRESS_MSB property returns
374the most significant 32 bits of the MAC address.
375Property 1 contains bits 47..32 of the MAC address.
376Property 2 contains bits 31..16 of the MAC address. */
377 HPI_ADAPTER_PROPERTY_MAC_ADDRESS_MSB = 260,
378
379/** Readonly adapter MAC address LSBs
380The MAC_ADDRESS_LSB property returns
381the least significant 16 bits of the MAC address.
382Property 1 contains bits 15..0 of the MAC address. */
383 HPI_ADAPTER_PROPERTY_MAC_ADDRESS_LSB = 261,
384
385/** Readonly extended adapter type number
386The EXTENDED_ADAPTER_TYPE property returns the 4 digits of an extended
387adapter type, i.e ASI8920-0022, 0022 is the extended type.
388The digits are returned as ASCII characters rather than the hex digits that
389are returned for the main type
390Property 1 returns the 1st two (left most) digits, i.e "00"
391in the example above, the upper byte being the left most digit.
392Property 2 returns the 2nd two digits, i.e "22" in the example above*/
393 HPI_ADAPTER_PROPERTY_EXTENDED_ADAPTER_TYPE = 262,
394
395/** Readonly debug log buffer information */
396 HPI_ADAPTER_PROPERTY_LOGTABLEN = 263,
397 HPI_ADAPTER_PROPERTY_LOGTABBEG = 264,
398
399/** Readonly adapter IP address
400For 192.168.1.101
401Property 1 returns the 1st two (left most) digits, i.e 192*256 + 168
402in the example above, the upper byte being the left most digit.
403Property 2 returns the 2nd two digits, i.e 1*256 + 101 in the example above, */
404 HPI_ADAPTER_PROPERTY_IP_ADDRESS = 265,
405
406/** Readonly adapter buffer processed count. Returns a buffer processed count
407that is incremented every time all buffers for all streams are updated. This
408is useful for checking completion of all stream operations across the adapter
409when using grouped streams.
410*/
411 HPI_ADAPTER_PROPERTY_BUFFER_UPDATE_COUNT = 266,
412
413/** Readonly mixer and stream intervals
414
415These intervals are measured in mixer frames.
416To convert to time, divide by the adapter samplerate.
417
418The mixer interval is the number of frames processed in one mixer iteration.
419The stream update interval is the interval at which streams check for and
420process data, and BBM host buffer counters are updated.
421
422Property 1 is the mixer interval in mixer frames.
423Property 2 is the stream update interval in mixer frames.
424*/
425 HPI_ADAPTER_PROPERTY_INTERVAL = 267,
426/** Adapter capabilities 1
427Property 1 - adapter can do multichannel (SSX1)
428Property 2 - adapter can do stream grouping (supports SSX2)
429*/
430 HPI_ADAPTER_PROPERTY_CAPS1 = 268,
431/** Adapter capabilities 2
432Property 1 - adapter can do samplerate conversion (MRX)
433Property 2 - adapter can do timestretch (TSX)
434*/
435 HPI_ADAPTER_PROPERTY_CAPS2 = 269
436};
437
438/** Adapter mode commands
439
440Used in wQueryOrSet field of HPI_AdapterSetModeEx().
441\ingroup adapter
442*/
443enum HPI_ADAPTER_MODE_CMDS {
444 HPI_ADAPTER_MODE_SET = 0,
445 HPI_ADAPTER_MODE_QUERY = 1
446};
447
448/** Adapter Modes
449 These are used by HPI_AdapterSetModeEx()
450
451\warning - more than 16 possible modes breaks
452a bitmask in the Windows WAVE DLL
453\ingroup adapter
454*/
455enum HPI_ADAPTER_MODES {
456/** 4 outstream mode.
457- ASI6114: 1 instream
458- ASI6044: 4 instreams
459- ASI6012: 1 instream
460- ASI6102: no instreams
461- ASI6022, ASI6122: 2 instreams
462- ASI5111, ASI5101: 2 instreams
463- ASI652x, ASI662x: 2 instreams
464- ASI654x, ASI664x: 4 instreams
465*/
466 HPI_ADAPTER_MODE_4OSTREAM = 1,
467
468/** 6 outstream mode.
469- ASI6012: 1 instream,
470- ASI6022, ASI6122: 2 instreams
471- ASI652x, ASI662x: 4 instreams
472*/
473 HPI_ADAPTER_MODE_6OSTREAM = 2,
474
475/** 8 outstream mode.
476- ASI6114: 8 instreams
477- ASI6118: 8 instreams
478- ASI6585: 8 instreams
479*/
480 HPI_ADAPTER_MODE_8OSTREAM = 3,
481
482/** 16 outstream mode.
483- ASI6416 16 instreams
484- ASI6518, ASI6618 16 instreams
485- ASI6118 16 mono out and in streams
486*/
487 HPI_ADAPTER_MODE_16OSTREAM = 4,
488
489/** one outstream mode.
490- ASI5111 1 outstream, 1 instream
491*/
492 HPI_ADAPTER_MODE_1OSTREAM = 5,
493
494/** ASI504X mode 1. 12 outstream, 4 instream 0 to 48kHz sample rates
495 (see ASI504X datasheet for more info).
496*/
497 HPI_ADAPTER_MODE_1 = 6,
498
499/** ASI504X mode 2. 4 outstreams, 4 instreams at 0 to 192kHz sample rates
500 (see ASI504X datasheet for more info).
501*/
502 HPI_ADAPTER_MODE_2 = 7,
503
504/** ASI504X mode 3. 4 outstreams, 4 instreams at 0 to 192kHz sample rates
505 (see ASI504X datasheet for more info).
506*/
507 HPI_ADAPTER_MODE_3 = 8,
508
509/** ASI504X multichannel mode.
510 2 outstreams -> 4 line outs = 1 to 8 channel streams),
511 4 lineins -> 1 instream (1 to 8 channel streams) at 0-48kHz.
512 For more info see the SSX Specification.
513*/
514 HPI_ADAPTER_MODE_MULTICHANNEL = 9,
515
516/** 12 outstream mode.
517- ASI6514, ASI6614: 2 instreams
518- ASI6540,ASI6544: 8 instreams
519- ASI6640,ASI6644: 8 instreams
520*/
521 HPI_ADAPTER_MODE_12OSTREAM = 10,
522
523/** 9 outstream mode.
524- ASI6044: 8 instreams
525*/
526 HPI_ADAPTER_MODE_9OSTREAM = 11,
527
528/** mono mode.
529- ASI6416: 16 outstreams/instreams
530- ASI5402: 2 outstreams/instreams
531*/
532 HPI_ADAPTER_MODE_MONO = 12,
533
534/** Low latency mode.
535- ASI6416/ASI6316: 1 16 channel outstream and instream
536*/
537 HPI_ADAPTER_MODE_LOW_LATENCY = 13
538};
539
540/* Note, adapters can have more than one capability -
541encoding as bitfield is recommended. */
542#define HPI_CAPABILITY_NONE (0)
543#define HPI_CAPABILITY_MPEG_LAYER3 (1)
544
545/* Set this equal to maximum capability index,
546Must not be greater than 32 - see axnvdef.h */
547#define HPI_CAPABILITY_MAX 1
548/* #define HPI_CAPABILITY_AAC 2 */
549
550/******************************************* STREAM ATTRIBUTES ****/
551
552/** MPEG Ancillary Data modes
553
554The mode for the ancillary data insertion or extraction to operate in.
555\ingroup stream
556*/
557enum HPI_MPEG_ANC_MODES {
558 /** the MPEG frames have energy information stored in them (5 bytes per stereo frame, 3 per mono) */
559 HPI_MPEG_ANC_HASENERGY = 0,
560 /** the entire ancillary data field is taken up by data from the Anc data buffer
561 On encode, the encoder will insert the energy bytes before filling the remainder
562 of the ancillary data space with data from the ancillary data buffer.
563 */
564 HPI_MPEG_ANC_RAW = 1
565};
566
567/** Ancillary Data Alignment
568\ingroup instream
569*/
570enum HPI_ISTREAM_MPEG_ANC_ALIGNS {
571 /** data is packed against the end of data, then padded to the end of frame */
572 HPI_MPEG_ANC_ALIGN_LEFT = 0,
573 /** data is packed against the end of the frame */
574 HPI_MPEG_ANC_ALIGN_RIGHT = 1
575};
576
577/** MPEG modes
578MPEG modes - can be used optionally for HPI_FormatCreate()
579parameter dwAttributes.
580
581Using any mode setting other than HPI_MPEG_MODE_DEFAULT
582with single channel format will return an error.
583\ingroup stream
584*/
585enum HPI_MPEG_MODES {
586/** Causes the MPEG-1 Layer II bitstream to be recorded
587in single_channel mode when the number of channels is 1 and in stereo when the
588number of channels is 2. */
589 HPI_MPEG_MODE_DEFAULT = 0,
590 /** Standard stereo without joint-stereo compression */
591 HPI_MPEG_MODE_STEREO = 1,
592 /** Joint stereo */
593 HPI_MPEG_MODE_JOINTSTEREO = 2,
594 /** Left and Right channels are completely independent */
595 HPI_MPEG_MODE_DUALCHANNEL = 3
596};
597/******************************************* MIXER ATTRIBUTES ****/
598
599/* \defgroup mixer_flags Mixer flags for HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES
600{
601*/
602#define HPI_MIXER_GET_CONTROL_MULTIPLE_CHANGED (0)
603#define HPI_MIXER_GET_CONTROL_MULTIPLE_RESET (1)
604/*}*/
605
606/** Commands used by HPI_MixerStore()
607\ingroup mixer
608*/
609enum HPI_MIXER_STORE_COMMAND {
610/** Save all mixer control settings. */
611 HPI_MIXER_STORE_SAVE = 1,
612/** Restore all controls from saved. */
613 HPI_MIXER_STORE_RESTORE = 2,
614/** Delete saved control settings. */
615 HPI_MIXER_STORE_DELETE = 3,
616/** Enable auto storage of some control settings. */
617 HPI_MIXER_STORE_ENABLE = 4,
618/** Disable auto storage of some control settings. */
619 HPI_MIXER_STORE_DISABLE = 5,
620/** Save the attributes of a single control. */
621 HPI_MIXER_STORE_SAVE_SINGLE = 6
622};
623
624/************************************* CONTROL ATTRIBUTE VALUES ****/
625/** Used by mixer plugin enable functions
626
627E.g. HPI_ParametricEQ_SetState()
628\ingroup mixer
629*/
630enum HPI_SWITCH_STATES {
631 HPI_SWITCH_OFF = 0, /**< turn the mixer plugin on. */
632 HPI_SWITCH_ON = 1 /**< turn the mixer plugin off. */
633};
634
635/* Volume control special gain values */
636/** volumes units are 100ths of a dB
637\ingroup volume
638*/
639#define HPI_UNITS_PER_dB 100
640/** turns volume control OFF or MUTE
641\ingroup volume
642*/
643#define HPI_GAIN_OFF (-100 * HPI_UNITS_PER_dB)
644
645/** value returned for no signal
646\ingroup meter
647*/
648#define HPI_METER_MINIMUM (-150 * HPI_UNITS_PER_dB)
649
650/** autofade profiles
651\ingroup volume
652*/
653enum HPI_VOLUME_AUTOFADES {
654/** log fade - dB attenuation changes linearly over time */
655 HPI_VOLUME_AUTOFADE_LOG = 2,
656/** linear fade - amplitude changes linearly */
657 HPI_VOLUME_AUTOFADE_LINEAR = 3
658};
659
660/** The physical encoding format of the AESEBU I/O.
661
662Used in HPI_AESEBU_Transmitter_SetFormat(), HPI_AESEBU_Receiver_SetFormat()
663along with related Get and Query functions
664\ingroup aestx
665*/
666enum HPI_AESEBU_FORMATS {
667/** AES/EBU physical format - AES/EBU balanced "professional" */
668 HPI_AESEBU_FORMAT_AESEBU = 1,
669/** AES/EBU physical format - S/PDIF unbalanced "consumer" */
670 HPI_AESEBU_FORMAT_SPDIF = 2
671};
672
673/** AES/EBU error status bits
674
675Returned by HPI_AESEBU_Receiver_GetErrorStatus()
676\ingroup aesrx
677*/
678enum HPI_AESEBU_ERRORS {
679/** bit0: 1 when PLL is not locked */
680 HPI_AESEBU_ERROR_NOT_LOCKED = 0x01,
681/** bit1: 1 when signal quality is poor */
682 HPI_AESEBU_ERROR_POOR_QUALITY = 0x02,
683/** bit2: 1 when there is a parity error */
684 HPI_AESEBU_ERROR_PARITY_ERROR = 0x04,
685/** bit3: 1 when there is a bi-phase coding violation */
686 HPI_AESEBU_ERROR_BIPHASE_VIOLATION = 0x08,
687/** bit4: 1 when the validity bit is high */
688 HPI_AESEBU_ERROR_VALIDITY = 0x10,
689/** bit5: 1 when the CRC error bit is high */
690 HPI_AESEBU_ERROR_CRC = 0x20
691};
692
693/** \addtogroup pad
694\{
695*/
696/** The text string containing the station/channel combination. */
697#define HPI_PAD_CHANNEL_NAME_LEN 16
698/** The text string containing the artist. */
699#define HPI_PAD_ARTIST_LEN 64
700/** The text string containing the title. */
701#define HPI_PAD_TITLE_LEN 64
702/** The text string containing the comment. */
703#define HPI_PAD_COMMENT_LEN 256
704/** The PTY when the tuner has not recieved any PTY. */
705#define HPI_PAD_PROGRAM_TYPE_INVALID 0xffff
706/** \} */
707
708/** Data types for PTY string translation.
709\ingroup rds
710*/
711enum eHPI_RDS_type {
712 HPI_RDS_DATATYPE_RDS = 0, /**< RDS bitstream.*/
713 HPI_RDS_DATATYPE_RBDS = 1 /**< RBDS bitstream.*/
714};
715
716/** Tuner bands
717
718Used for HPI_Tuner_SetBand(),HPI_Tuner_GetBand()
719\ingroup tuner
720*/
721enum HPI_TUNER_BAND {
722 HPI_TUNER_BAND_AM = 1, /**< AM band */
723 HPI_TUNER_BAND_FM = 2, /**< FM band (mono) */
724 HPI_TUNER_BAND_TV_NTSC_M = 3, /**< NTSC-M TV band*/
725 HPI_TUNER_BAND_TV = 3, /* use TV_NTSC_M */
726 HPI_TUNER_BAND_FM_STEREO = 4, /**< FM band (stereo) */
727 HPI_TUNER_BAND_AUX = 5, /**< auxiliary input */
728 HPI_TUNER_BAND_TV_PAL_BG = 6, /**< PAL-B/G TV band*/
729 HPI_TUNER_BAND_TV_PAL_I = 7, /**< PAL-I TV band*/
730 HPI_TUNER_BAND_TV_PAL_DK = 8, /**< PAL-D/K TV band*/
731 HPI_TUNER_BAND_TV_SECAM_L = 9, /**< SECAM-L TV band*/
732 HPI_TUNER_BAND_LAST = 9 /**< the index of the last tuner band. */
733};
734
735/** Tuner mode attributes
736
737Used by HPI_Tuner_SetMode(), HPI_Tuner_GetMode()
738\ingroup tuner
739
740*/
741enum HPI_TUNER_MODES {
742 HPI_TUNER_MODE_RSS = 1, /**< control RSS */
743 HPI_TUNER_MODE_RDS = 2 /**< control RBDS/RDS */
744};
745
746/** Tuner mode attribute values
747
748Used by HPI_Tuner_SetMode(), HPI_Tuner_GetMode()
749\ingroup tuner
750*/
751enum HPI_TUNER_MODE_VALUES {
752/* RSS attribute values */
753 HPI_TUNER_MODE_RSS_DISABLE = 0, /**< RSS disable */
754 HPI_TUNER_MODE_RSS_ENABLE = 1, /**< RSS enable */
755
756/* RDS mode attributes */
757 HPI_TUNER_MODE_RDS_DISABLE = 0, /**< RDS - disabled */
758 HPI_TUNER_MODE_RDS_RDS = 1, /**< RDS - RDS mode */
759 HPI_TUNER_MODE_RDS_RBDS = 2 /**< RDS - RBDS mode */
760};
761
762/** Tuner Level settings
763\ingroup tuner
764*/
765enum HPI_TUNER_LEVEL {
766 HPI_TUNER_LEVEL_AVERAGE = 0,
767 HPI_TUNER_LEVEL_RAW = 1
768};
769
770/** Tuner Status Bits
771
772These bitfield values are returned by a call to HPI_Tuner_GetStatus().
773Multiple fields are returned from a single call.
774\ingroup tuner
775*/
776enum HPI_TUNER_STATUS_BITS {
777 HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001, /**< video color is present. */
778 HPI_TUNER_VIDEO_IS_60HZ = 0x0020, /**< 60 hz video detected. */
779 HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040, /**< video HSYNC is missing. */
780 HPI_TUNER_VIDEO_STATUS_VALID = 0x0100, /**< video status is valid. */
781 HPI_TUNER_PLL_LOCKED = 0x1000, /**< the tuner's PLL is locked. */
782 HPI_TUNER_FM_STEREO = 0x2000, /**< tuner reports back FM stereo. */
783 HPI_TUNER_DIGITAL = 0x0200, /**< tuner reports digital programming. */
784 HPI_TUNER_MULTIPROGRAM = 0x0400 /**< tuner reports multiple programs. */
785};
786
787/** Channel Modes
788Used for HPI_ChannelModeSet/Get()
789\ingroup channelmode
790*/
791enum HPI_CHANNEL_MODES {
792/** Left channel out = left channel in, Right channel out = right channel in. */
793 HPI_CHANNEL_MODE_NORMAL = 1,
794/** Left channel out = right channel in, Right channel out = left channel in. */
795 HPI_CHANNEL_MODE_SWAP = 2,
796/** Left channel out = left channel in, Right channel out = left channel in. */
797 HPI_CHANNEL_MODE_LEFT_TO_STEREO = 3,
798/** Left channel out = right channel in, Right channel out = right channel in.*/
799 HPI_CHANNEL_MODE_RIGHT_TO_STEREO = 4,
800/** Left channel out = (left channel in + right channel in)/2,
801 Right channel out = mute. */
802 HPI_CHANNEL_MODE_STEREO_TO_LEFT = 5,
803/** Left channel out = mute,
804 Right channel out = (right channel in + left channel in)/2. */
805 HPI_CHANNEL_MODE_STEREO_TO_RIGHT = 6,
806 HPI_CHANNEL_MODE_LAST = 6
807};
808
809/** SampleClock source values
810\ingroup sampleclock
811*/
812enum HPI_SAMPLECLOCK_SOURCES {
813/** The sampleclock output is derived from its local samplerate generator.
814 The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */
815 HPI_SAMPLECLOCK_SOURCE_LOCAL = 1,
816/** \deprecated Use HPI_SAMPLECLOCK_SOURCE_LOCAL instead */
817 HPI_SAMPLECLOCK_SOURCE_ADAPTER = 1,
818/** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/
819 HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2,
820/** From external wordclock connector */
821 HPI_SAMPLECLOCK_SOURCE_WORD = 3,
822/** Board-to-board header */
823 HPI_SAMPLECLOCK_SOURCE_WORD_HEADER = 4,
824/** FUTURE - SMPTE clock. */
825 HPI_SAMPLECLOCK_SOURCE_SMPTE = 5,
826/** One of the aesebu inputs */
827 HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6,
828/** \deprecated The first aesebu input with a valid signal
829Superseded by separate Auto enable flag
830*/
831 HPI_SAMPLECLOCK_SOURCE_AESEBU_AUTO = 7,
832/** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */
833 HPI_SAMPLECLOCK_SOURCE_NETWORK = 8,
834/** From previous adjacent module (ASI2416 only)*/
835 HPI_SAMPLECLOCK_SOURCE_PREV_MODULE = 10,
836/*! Update this if you add a new clock source.*/
837 HPI_SAMPLECLOCK_SOURCE_LAST = 10
838};
839
840/** Equalizer filter types. Used by HPI_ParametricEQ_SetBand()
841\ingroup parmeq
842*/
843enum HPI_FILTER_TYPE {
844 HPI_FILTER_TYPE_BYPASS = 0, /**< filter is turned off */
845
846 HPI_FILTER_TYPE_LOWSHELF = 1, /**< EQ low shelf */
847 HPI_FILTER_TYPE_HIGHSHELF = 2, /**< EQ high shelf */
848 HPI_FILTER_TYPE_EQ_BAND = 3, /**< EQ gain */
849
850 HPI_FILTER_TYPE_LOWPASS = 4, /**< standard low pass */
851 HPI_FILTER_TYPE_HIGHPASS = 5, /**< standard high pass */
852 HPI_FILTER_TYPE_BANDPASS = 6, /**< standard band pass */
853 HPI_FILTER_TYPE_BANDSTOP = 7 /**< standard band stop/notch */
854};
855
856/** Async Event sources
857\ingroup async
858*/
859enum ASYNC_EVENT_SOURCES {
860 HPI_ASYNC_EVENT_GPIO = 1, /**< GPIO event. */
861 HPI_ASYNC_EVENT_SILENCE = 2, /**< silence event detected. */
862 HPI_ASYNC_EVENT_TONE = 3 /**< tone event detected. */
863};
864/*******************************************/
865/** HPI Error codes
866
867Almost all HPI functions return an error code
868A return value of zero means there was no error.
869Otherwise one of these error codes is returned.
870Error codes can be converted to a descriptive string using HPI_GetErrorText()
871
872\note When a new error code is added HPI_GetErrorText() MUST be updated.
873\note Codes 1-100 are reserved for driver use
874\ingroup utility
875*/
876enum HPI_ERROR_CODES {
877 /** Message type does not exist. */
878 HPI_ERROR_INVALID_TYPE = 100,
879 /** Object type does not exist. */
880 HPI_ERROR_INVALID_OBJ = 101,
881 /** Function does not exist. */
882 HPI_ERROR_INVALID_FUNC = 102,
883 /** The specified object (adapter/Stream) does not exist. */
884 HPI_ERROR_INVALID_OBJ_INDEX = 103,
885 /** Trying to access an object that has not been opened yet. */
886 HPI_ERROR_OBJ_NOT_OPEN = 104,
887 /** Trying to open an already open object. */
888 HPI_ERROR_OBJ_ALREADY_OPEN = 105,
889 /** PCI, ISA resource not valid. */
890 HPI_ERROR_INVALID_RESOURCE = 106,
891 /** GetInfo call from SubSysFindAdapters failed. */
892 HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO = 107,
893 /** Default response was never updated with actual error code. */
894 HPI_ERROR_INVALID_RESPONSE = 108,
895 /** wSize field of response was not updated,
896 indicating that the message was not processed. */
897 HPI_ERROR_PROCESSING_MESSAGE = 109,
898 /** The network did not respond in a timely manner. */
899 HPI_ERROR_NETWORK_TIMEOUT = 110,
900 /** An HPI handle is invalid (uninitialised?). */
901 HPI_ERROR_INVALID_HANDLE = 111,
902 /** A function or attribute has not been implemented yet. */
903 HPI_ERROR_UNIMPLEMENTED = 112,
904 /** There are too many clients attempting to access a network resource. */
905 HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113,
906 /** Response buffer passed to HPI_Message was smaller than returned response */
907 HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114,
908 /** The returned response did not match the sent message */
909 HPI_ERROR_RESPONSE_MISMATCH = 115,
910
911 /** Too many adapters.*/
912 HPI_ERROR_TOO_MANY_ADAPTERS = 200,
913 /** Bad adpater. */
914 HPI_ERROR_BAD_ADAPTER = 201,
915 /** Adapter number out of range or not set properly. */
916 HPI_ERROR_BAD_ADAPTER_NUMBER = 202,
917 /** 2 adapters with the same adapter number. */
918 HPI_DUPLICATE_ADAPTER_NUMBER = 203,
919 /** DSP code failed to bootload. */
920 HPI_ERROR_DSP_BOOTLOAD = 204,
921 /** Adapter failed DSP code self test. */
922 HPI_ERROR_DSP_SELFTEST = 205,
923 /** Couldn't find or open the DSP code file. */
924 HPI_ERROR_DSP_FILE_NOT_FOUND = 206,
925 /** Internal DSP hardware error. */
926 HPI_ERROR_DSP_HARDWARE = 207,
927 /** Could not allocate memory in DOS. */
928 HPI_ERROR_DOS_MEMORY_ALLOC = 208,
929 /** Could not allocate memory */
930 HPI_ERROR_MEMORY_ALLOC = 208,
931 /** Failed to correctly load/config PLD .*/
932 HPI_ERROR_PLD_LOAD = 209,
933 /** Unexpected end of file, block length too big etc. */
934 HPI_ERROR_DSP_FILE_FORMAT = 210,
935
936 /** Found but could not open DSP code file. */
937 HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211,
938 /** First DSP code section header not found in DSP file. */
939 HPI_ERROR_DSP_FILE_NO_HEADER = 212,
940 /** File read operation on DSP code file failed. */
941 HPI_ERROR_DSP_FILE_READ_ERROR = 213,
942 /** DSP code for adapter family not found. */
943 HPI_ERROR_DSP_SECTION_NOT_FOUND = 214,
944 /** Other OS specific error opening DSP file. */
945 HPI_ERROR_DSP_FILE_OTHER_ERROR = 215,
946 /** Sharing violation opening DSP code file. */
947 HPI_ERROR_DSP_FILE_SHARING_VIOLATION = 216,
948 /** DSP code section header had size == 0. */
949 HPI_ERROR_DSP_FILE_NULL_HEADER = 217,
950
951 /** Base number for flash errors. */
952 HPI_ERROR_FLASH = 220,
953
954 /** Flash has bad checksum */
955 HPI_ERROR_BAD_CHECKSUM = (HPI_ERROR_FLASH + 1),
956 HPI_ERROR_BAD_SEQUENCE = (HPI_ERROR_FLASH + 2),
957 HPI_ERROR_FLASH_ERASE = (HPI_ERROR_FLASH + 3),
958 HPI_ERROR_FLASH_PROGRAM = (HPI_ERROR_FLASH + 4),
959 HPI_ERROR_FLASH_VERIFY = (HPI_ERROR_FLASH + 5),
960 HPI_ERROR_FLASH_TYPE = (HPI_ERROR_FLASH + 6),
961 HPI_ERROR_FLASH_START = (HPI_ERROR_FLASH + 7),
962
963 /** Reserved for OEMs. */
964 HPI_ERROR_RESERVED_1 = 290,
965
966 /** Stream does not exist. */
967 HPI_ERROR_INVALID_STREAM = 300,
968 /** Invalid compression format. */
969 HPI_ERROR_INVALID_FORMAT = 301,
970 /** Invalid format samplerate */
971 HPI_ERROR_INVALID_SAMPLERATE = 302,
972 /** Invalid format number of channels. */
973 HPI_ERROR_INVALID_CHANNELS = 303,
974 /** Invalid format bitrate. */
975 HPI_ERROR_INVALID_BITRATE = 304,
976 /** Invalid datasize used for stream read/write. */
977 HPI_ERROR_INVALID_DATASIZE = 305,
978 /** Stream buffer is full during stream write. */
979 HPI_ERROR_BUFFER_FULL = 306,
980 /** Stream buffer is empty during stream read. */
981 HPI_ERROR_BUFFER_EMPTY = 307,
982 /** Invalid datasize used for stream read/write. */
983 HPI_ERROR_INVALID_DATA_TRANSFER = 308,
984 /** Packet ordering error for stream read/write. */
985 HPI_ERROR_INVALID_PACKET_ORDER = 309,
986
987 /** Object can't do requested operation in its current
988 state, eg set format, change rec mux state while recording.*/
989 HPI_ERROR_INVALID_OPERATION = 310,
990
991 /** Where an SRG is shared amongst streams, an incompatible samplerate is one
992 that is different to any currently playing or recording stream. */
993 HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311,
994 /** Adapter mode is illegal.*/
995 HPI_ERROR_BAD_ADAPTER_MODE = 312,
996
997 /** There have been too many attempts to set the adapter's
998 capabilities (using bad keys), the card should be returned
999 to ASI if further capabilities updates are required */
1000 HPI_ERROR_TOO_MANY_CAPABILITY_CHANGE_ATTEMPTS = 313,
1001 /** Streams on different adapters cannot be grouped. */
1002 HPI_ERROR_NO_INTERADAPTER_GROUPS = 314,
1003 /** Streams on different DSPs cannot be grouped. */
1004 HPI_ERROR_NO_INTERDSP_GROUPS = 315,
1005
1006 /** Invalid mixer node for this adapter. */
1007 HPI_ERROR_INVALID_NODE = 400,
1008 /** Invalid control. */
1009 HPI_ERROR_INVALID_CONTROL = 401,
1010 /** Invalid control value was passed. */
1011 HPI_ERROR_INVALID_CONTROL_VALUE = 402,
1012 /** Control attribute not supported by this control. */
1013 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE = 403,
1014 /** Control is disabled. */
1015 HPI_ERROR_CONTROL_DISABLED = 404,
1016 /** I2C transaction failed due to a missing ACK. */
1017 HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405,
1018 /** Control attribute is valid, but not supported by this hardware. */
1019 HPI_ERROR_UNSUPPORTED_CONTROL_ATTRIBUTE = 406,
1020 /** Control is busy, or coming out of
1021 reset and cannot be accessed at this time. */
1022 HPI_ERROR_CONTROL_NOT_READY = 407,
1023
1024 /** Non volatile memory */
1025 HPI_ERROR_NVMEM_BUSY = 450,
1026 HPI_ERROR_NVMEM_FULL = 451,
1027 HPI_ERROR_NVMEM_FAIL = 452,
1028
1029 /** I2C */
1030 HPI_ERROR_I2C_MISSING_ACK = HPI_ERROR_CONTROL_I2C_MISSING_ACK,
1031 HPI_ERROR_I2C_BAD_ADR = 460,
1032
1033 /** Entity errors */
1034 HPI_ERROR_ENTITY_TYPE_MISMATCH = 470,
1035 HPI_ERROR_ENTITY_ITEM_COUNT = 471,
1036 HPI_ERROR_ENTITY_TYPE_INVALID = 472,
1037 HPI_ERROR_ENTITY_ROLE_INVALID = 473,
1038
1039 /* AES18 specific errors were 500..507 */
1040
1041 /** custom error to use for debugging */
1042 HPI_ERROR_CUSTOM = 600,
1043
1044 /** hpioct32.c can't obtain mutex */
1045 HPI_ERROR_MUTEX_TIMEOUT = 700,
1046
1047 /** errors from HPI backends have values >= this */
1048 HPI_ERROR_BACKEND_BASE = 900,
1049
1050 /** indicates a cached u16 value is invalid. */
1051 HPI_ERROR_ILLEGAL_CACHE_VALUE = 0xffff
1052};
1053
1054/** \defgroup maximums HPI maximum values
1055\{
1056*/
1057/** Maximum number of adapters per HPI sub-system
1058 WARNING: modifying this value changes the response structure size.*/
1059#define HPI_MAX_ADAPTERS 20
1060/** Maximum number of in or out streams per adapter */
1061#define HPI_MAX_STREAMS 16
1062#define HPI_MAX_CHANNELS 2 /* per stream */
1063#define HPI_MAX_NODES 8 /* per mixer ? */
1064#define HPI_MAX_CONTROLS 4 /* per node ? */
1065/** maximum number of ancillary bytes per MPEG frame */
1066#define HPI_MAX_ANC_BYTES_PER_FRAME (64)
1067#define HPI_STRING_LEN 16
1068
1069/** Velocity units */
1070#define HPI_OSTREAM_VELOCITY_UNITS 4096
1071/** OutStream timescale units */
1072#define HPI_OSTREAM_TIMESCALE_UNITS 10000
1073/** OutStream timescale passthrough - turns timescaling on in passthough mode */
1074#define HPI_OSTREAM_TIMESCALE_PASSTHROUGH 99999
1075
1076/**\}*/
1077
1078/* ////////////////////////////////////////////////////////////////////// */
1079/* STRUCTURES */
1080#ifndef DISABLE_PRAGMA_PACK1
1081#pragma pack(push, 1)
1082#endif
1083
1084/** Structure containing sample format information.
1085 See also HPI_FormatCreate().
1086 */
1087struct hpi_format {
1088 u32 sample_rate;
1089 /**< 11025, 32000, 44100 ... */
1090 u32 bit_rate; /**< for MPEG */
1091 u32 attributes;
1092 /**< Stereo/JointStereo/Mono */
1093 u16 mode_legacy;
1094 /**< Legacy ancillary mode or idle bit */
1095 u16 unused; /**< unused */
1096 u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
1097 u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */
1098};
1099
1100struct hpi_anc_frame {
1101 u32 valid_bits_in_this_frame;
1102 u8 b_data[HPI_MAX_ANC_BYTES_PER_FRAME];
1103};
1104
1105/** An object for containing a single async event.
1106*/
1107struct hpi_async_event {
1108 u16 event_type; /**< type of event. \sa async_event */
1109 u16 sequence; /**< sequence number, allows lost event detection */
1110 u32 state; /**< new state */
1111 u32 h_object; /**< handle to the object returning the event. */
1112 union {
1113 struct {
1114 u16 index; /**< GPIO bit index. */
1115 } gpio;
1116 struct {
1117 u16 node_index; /**< what node is the control on ? */
1118 u16 node_type; /**< what type of node is the control on ? */
1119 } control;
1120 } u;
1121};
1122
1123/*/////////////////////////////////////////////////////////////////////////// */
1124/* Public HPI Entity related definitions */
1125
1126struct hpi_entity;
1127
1128enum e_entity_type {
1129 entity_type_null,
1130 entity_type_sequence, /* sequence of potentially heterogeneous TLV entities */
1131
1132 entity_type_reference, /* refers to a TLV entity or NULL */
1133
1134 entity_type_int, /* 32 bit */
1135 entity_type_float, /* ieee754 binary 32 bit encoding */
1136 entity_type_double,
1137
1138 entity_type_cstring,
1139 entity_type_octet,
1140 entity_type_ip4_address,
1141 entity_type_ip6_address,
1142 entity_type_mac_address,
1143
1144 LAST_ENTITY_TYPE
1145};
1146
1147enum e_entity_role {
1148 entity_role_null,
1149 entity_role_value,
1150 entity_role_classname,
1151
1152 entity_role_units,
1153 entity_role_flags,
1154 entity_role_range,
1155
1156 entity_role_mapping,
1157 entity_role_enum,
1158
1159 entity_role_instance_of,
1160 entity_role_depends_on,
1161 entity_role_member_of_group,
1162 entity_role_value_constraint,
1163 entity_role_parameter_port,
1164
1165 entity_role_block,
1166 entity_role_node_group,
1167 entity_role_audio_port,
1168 entity_role_clock_port,
1169 LAST_ENTITY_ROLE
1170};
1171
1172/* skip host side function declarations for
1173 DSP compile and documentation extraction */
1174
1175struct hpi_hsubsys {
1176 int not_really_used;
1177};
1178
1179#ifndef DISABLE_PRAGMA_PACK1
1180#pragma pack(pop)
1181#endif
1182
1183/*////////////////////////////////////////////////////////////////////////// */
1184/* HPI FUNCTIONS */
1185
1186/*/////////////////////////// */
1187/* DATA and FORMAT and STREAM */
1188
1189u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF,
1190 u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size);
1191
1192/*/////////// */
1193/* SUB SYSTEM */
1194struct hpi_hsubsys *hpi_subsys_create(void
1195 );
1196
1197void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys);
1198
1199u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys,
1200 u32 *pversion);
1201
1202u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys,
1203 u32 *pversion_ex);
1204
1205u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion,
1206 u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length);
1207
1208u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys,
1209 u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length);
1210
1211u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys,
1212 int *pn_num_adapters);
1213
1214u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator,
1215 u32 *padapter_index, u16 *pw_adapter_type);
1216
1217u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass);
1218
1219u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys,
1220 const char *sz_interface);
1221
1222/*///////// */
1223/* ADAPTER */
1224
1225u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index);
1226
1227u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index);
1228
1229u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys,
1230 u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams,
1231 u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type);
1232
1233u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys,
1234 u16 adapter_index, u16 module_index, u16 *pw_num_outputs,
1235 u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number,
1236 u16 *pw_module_type, u32 *ph_module);
1237
1238u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys,
1239 u16 adapter_index, u32 adapter_mode);
1240
1241u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
1242 u16 adapter_index, u32 adapter_mode, u16 query_or_set);
1243
1244u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys,
1245 u16 adapter_index, u32 *padapter_mode);
1246
1247u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys,
1248 u16 adapter_index, u16 *assert_present, char *psz_assert,
1249 u16 *pw_line_number);
1250
1251u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys,
1252 u16 adapter_index, u16 *assert_present, char *psz_assert,
1253 u32 *pline_number, u16 *pw_assert_on_dsp);
1254
1255u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys,
1256 u16 adapter_index, u16 assert_id);
1257
1258u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys,
1259 u16 adapter_index, u16 capability, u32 key);
1260
1261u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys,
1262 u16 adapter_index);
1263
1264u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
1265 u16 adapter_index, u32 dsp_address, char *p_bytes, int *count_bytes);
1266
1267u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys,
1268 u16 adapter_index, u16 property, u16 paramter1, u16 paramter2);
1269
1270u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys,
1271 u16 adapter_index, u16 property, u16 *pw_paramter1,
1272 u16 *pw_paramter2);
1273
1274u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys,
1275 u16 adapter_index, u16 index, u16 what_to_enumerate,
1276 u16 property_index, u32 *psetting);
1277
1278/*////////////// */
1279/* NonVol Memory */
1280u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1281 u32 *ph_nv_memory, u16 *pw_size_in_bytes);
1282
1283u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys,
1284 u32 h_nv_memory, u16 index, u16 *pw_data);
1285
1286u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys,
1287 u32 h_nv_memory, u16 index, u16 data);
1288
1289/*////////////// */
1290/* Digital I/O */
1291u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1292 u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits);
1293
1294u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
1295 u16 bit_index, u16 *pw_bit_data);
1296
1297u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
1298 u16 aw_all_bit_data[4]
1299 );
1300
1301u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
1302 u16 bit_index, u16 bit_data);
1303
1304u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
1305 u16 aw_all_bit_data[4]
1306 );
1307
1308/**********************/
1309/* Async Event Object */
1310/**********************/
1311u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys,
1312 u16 adapter_index, u32 *ph_async);
1313
1314u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async);
1315
1316u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
1317 u16 maximum_events, struct hpi_async_event *p_events,
1318 u16 *pw_number_returned);
1319
1320u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys,
1321 u32 h_async, u16 *pw_count);
1322
1323u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async,
1324 u16 maximum_events, struct hpi_async_event *p_events,
1325 u16 *pw_number_returned);
1326
1327/*/////////// */
1328/* WATCH-DOG */
1329u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1330 u32 *ph_watchdog);
1331
1332u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog,
1333 u32 time_millisec);
1334
1335u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog);
1336
1337/**************/
1338/* OUT STREAM */
1339/**************/
1340u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1341 u16 outstream_index, u32 *ph_outstream);
1342
1343u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
1344
1345u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
1346 u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play,
1347 u32 *psamples_played, u32 *pauxiliary_data_to_play);
1348
1349u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys,
1350 u32 h_outstream, const u8 *pb_write_buf, u32 bytes_to_write,
1351 const struct hpi_format *p_format);
1352
1353u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
1354
1355u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys,
1356 u32 h_outstream);
1357
1358u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
1359
1360u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys,
1361 u32 h_outstream);
1362
1363u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
1364
1365u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys,
1366 u32 h_outstream, struct hpi_format *p_format);
1367
1368u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys,
1369 u32 h_outstream, struct hpi_format *p_format);
1370
1371u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys,
1372 u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample);
1373
1374u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys,
1375 u32 h_outstream, short velocity);
1376
1377u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
1378 u32 h_outstream, u16 mode);
1379
1380u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
1381 u32 h_outstream, u32 *pframes_available);
1382
1383u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
1384 u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer,
1385 u32 anc_frame_buffer_size_in_bytes,
1386 u32 number_of_ancillary_frames_to_read);
1387
1388u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys,
1389 u32 h_outstream, u32 time_scaleX10000);
1390
1391u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
1392 u32 h_outstream, u32 size_in_bytes);
1393
1394u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
1395 u32 h_outstream);
1396
1397u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
1398 u32 h_outstream, u32 h_stream);
1399
1400u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys,
1401 u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map);
1402
1403u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys,
1404 u32 h_outstream);
1405
1406/*////////// */
1407/* IN_STREAM */
1408u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1409 u16 instream_index, u32 *ph_instream);
1410
1411u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
1412
1413u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys,
1414 u32 h_instream, const struct hpi_format *p_format);
1415
1416u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys,
1417 u32 h_instream, const struct hpi_format *p_format);
1418
1419u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream,
1420 u8 *pb_read_buf, u32 bytes_to_read);
1421
1422u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
1423
1424u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys,
1425 u32 h_instream);
1426
1427u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
1428
1429u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
1430
1431u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
1432 u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded,
1433 u32 *psamples_recorded, u32 *pauxiliary_data_recorded);
1434
1435u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
1436 u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment,
1437 u16 idle_bit);
1438
1439u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
1440 u32 h_instream, u32 *pframe_space);
1441
1442u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
1443 u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer,
1444 u32 anc_frame_buffer_size_in_bytes,
1445 u32 number_of_ancillary_frames_to_write);
1446
1447u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
1448 u32 h_instream, u32 size_in_bytes);
1449
1450u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
1451 u32 h_instream);
1452
1453u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
1454 u32 h_instream, u32 h_stream);
1455
1456u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys,
1457 u32 h_instream, u32 *poutstream_map, u32 *pinstream_map);
1458
1459u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys,
1460 u32 h_instream);
1461
1462/*********/
1463/* MIXER */
1464/*********/
1465u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1466 u32 *ph_mixer);
1467
1468u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer);
1469
1470u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
1471 u16 src_node_type, u16 src_node_type_index, u16 dst_node_type,
1472 u16 dst_node_type_index, u16 control_type, u32 *ph_control);
1473
1474u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys,
1475 u32 h_mixer, u16 control_index, u16 *pw_src_node_type,
1476 u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index,
1477 u16 *pw_control_type, u32 *ph_control);
1478
1479u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
1480 enum HPI_MIXER_STORE_COMMAND command, u16 index);
1481/*************************/
1482/* mixer CONTROLS */
1483/*************************/
1484/*************************/
1485/* volume control */
1486/*************************/
1487u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1488 short an_gain0_01dB[HPI_MAX_CHANNELS]
1489 );
1490
1491u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1492 short an_gain0_01dB_out[HPI_MAX_CHANNELS]
1493 );
1494
1495#define hpi_volume_get_range hpi_volume_query_range
1496u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1497 short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB);
1498
1499u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
1500 const u32 h_volume, u32 *p_channels);
1501
1502u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1503 short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms);
1504
1505u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
1506 u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS],
1507 u32 duration_ms, u16 profile);
1508
1509/*************************/
1510/* level control */
1511/*************************/
1512u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1513 short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB);
1514
1515u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1516 short an_gain0_01dB[HPI_MAX_CHANNELS]
1517 );
1518
1519u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1520 short an_gain0_01dB_out[HPI_MAX_CHANNELS]
1521 );
1522
1523/*************************/
1524/* meter control */
1525/*************************/
1526u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
1527 const u32 h_meter, u32 *p_channels);
1528
1529u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1530 short an_peak0_01dB_out[HPI_MAX_CHANNELS]
1531 );
1532
1533u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1534 short an_peak0_01dB_out[HPI_MAX_CHANNELS]
1535 );
1536
1537u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
1538 u32 h_control, u16 attack, u16 decay);
1539
1540u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
1541 u32 h_control, u16 attack, u16 decay);
1542
1543u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
1544 u32 h_control, u16 *attack, u16 *decay);
1545
1546u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
1547 u32 h_control, u16 *attack, u16 *decay);
1548
1549/*************************/
1550/* channel mode control */
1551/*************************/
1552u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys,
1553 const u32 h_mode, const u32 index, u16 *pw_mode);
1554
1555u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1556 u16 mode);
1557
1558u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1559 u16 *mode);
1560
1561/*************************/
1562/* Tuner control */
1563/*************************/
1564u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
1565 const u32 h_tuner, const u32 index, u16 *pw_band);
1566
1567u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1568 u16 band);
1569
1570u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1571 u16 *pw_band);
1572
1573u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys,
1574 const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq);
1575
1576u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys,
1577 u32 h_control, u32 freq_ink_hz);
1578
1579u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys,
1580 u32 h_control, u32 *pw_freq_ink_hz);
1581
1582u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1583 short *pw_level);
1584
1585u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
1586 u32 h_control, short *pw_level);
1587
1588u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys,
1589 const u32 h_tuner, const u32 index, u16 *pw_gain);
1590
1591u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1592 short gain);
1593
1594u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1595 short *pn_gain);
1596
1597u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1598 u16 *pw_status_mask, u16 *pw_status);
1599
1600u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1601 u32 mode, u32 value);
1602
1603u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1604 u32 mode, u32 *pn_value);
1605
1606u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1607 char *p_rds_data);
1608
1609u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys,
1610 const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis);
1611
1612u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys,
1613 u32 h_control, u32 deemphasis);
1614u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys,
1615 u32 h_control, u32 *pdeemphasis);
1616
1617u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys,
1618 const u32 h_tuner, u32 *pbitmap_program);
1619
1620u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1621 u32 program);
1622
1623u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1624 u32 *pprogram);
1625
1626u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
1627 u32 h_control, char *psz_dsp_version, const u32 string_size);
1628
1629u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
1630 u32 h_control, char *psz_sdk_version, const u32 string_size);
1631
1632u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
1633 u32 h_control, u32 *pquality);
1634
1635/****************************/
1636/* PADs control */
1637/****************************/
1638
1639u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
1640 u32 h_control, char *psz_string, const u32 string_length);
1641
1642u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1643 char *psz_string, const u32 string_length);
1644
1645u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1646 char *psz_string, const u32 string_length);
1647
1648u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1649 char *psz_string, const u32 string_length);
1650
1651u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
1652 u32 h_control, u32 *ppTY);
1653
1654u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1655 u32 *ppI);
1656
1657u16 HPI_PAD__get_program_type_string(const struct hpi_hsubsys *ph_subsys,
1658 u32 h_control, const u32 data_type, const u32 pTY, char *psz_string,
1659 const u32 string_length);
1660
1661/****************************/
1662/* AES/EBU Receiver control */
1663/****************************/
1664u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys,
1665 const u32 h_aes_rx, const u32 index, u16 *pw_format);
1666
1667u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys,
1668 u32 h_control, u16 source);
1669
1670u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys,
1671 u32 h_control, u16 *pw_source);
1672
1673u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
1674 u32 h_control, u32 *psample_rate);
1675
1676u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys,
1677 u32 h_control, u16 index, u16 *pw_data);
1678
1679u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys
1680 *ph_subsys, u32 h_control, u16 index, u16 *pw_data);
1681
1682u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys,
1683 u32 h_control, u16 *pw_error_data);
1684
1685/*******************************/
1686/* AES/EBU Transmitter control */
1687/*******************************/
1688u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys
1689 *ph_subsys, u32 h_control, u32 sample_rate);
1690
1691u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys,
1692 u32 h_control, u16 index, u16 data);
1693
1694u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys
1695 *ph_subsys, u32 h_control, u16 index, u16 data);
1696
1697u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys
1698 *ph_subsys, u32 h_control, u16 index, u16 *pw_data);
1699
1700u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys,
1701 const u32 h_aes_tx, const u32 index, u16 *pw_format);
1702
1703u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys,
1704 u32 h_control, u16 output_format);
1705
1706u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys,
1707 u32 h_control, u16 *pw_output_format);
1708
1709/***********************/
1710/* multiplexer control */
1711/***********************/
1712u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys,
1713 u32 h_control, u16 source_node_type, u16 source_node_index);
1714
1715u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys,
1716 u32 h_control, u16 *source_node_type, u16 *source_node_index);
1717
1718u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys,
1719 u32 h_control, u16 index, u16 *source_node_type,
1720 u16 *source_node_index);
1721
1722/***************/
1723/* VOX control */
1724/***************/
1725u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1726 short an_gain0_01dB);
1727
1728u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1729 short *an_gain0_01dB);
1730
1731/*********************/
1732/* Bitstream control */
1733/*********************/
1734u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys,
1735 u32 h_control, u16 edge_type);
1736
1737u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys,
1738 u32 h_control, u16 polarity);
1739
1740u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys,
1741 u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity);
1742
1743/***********************/
1744/* SampleClock control */
1745/***********************/
1746
1747u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys,
1748 const u32 h_clock, const u32 index, u16 *pw_source);
1749
1750u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys,
1751 u32 h_control, u16 source);
1752
1753u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys,
1754 u32 h_control, u16 *pw_source);
1755
1756u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys,
1757 const u32 h_clock, const u32 index, const u32 source,
1758 u16 *pw_source_index);
1759
1760u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys,
1761 u32 h_control, u16 source_index);
1762
1763u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys,
1764 u32 h_control, u16 *pw_source_index);
1765
1766u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
1767 u32 h_control, u32 *psample_rate);
1768
1769u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys,
1770 const u32 h_clock, const u32 index, u32 *psource);
1771
1772u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys,
1773 u32 h_control, u32 sample_rate);
1774
1775u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys,
1776 u32 h_control, u32 *psample_rate);
1777
1778u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys,
1779 u32 h_control, u32 enable);
1780
1781u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys,
1782 u32 h_control, u32 *penable);
1783
1784u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
1785 u32 h_control, u32 lock);
1786
1787u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
1788 u32 h_control, u32 *plock);
1789
1790/***********************/
1791/* Microphone control */
1792/***********************/
1793u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys,
1794 u32 h_control, u16 on_off);
1795
1796u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys,
1797 u32 h_control, u16 *pw_on_off);
1798
1799/*******************************
1800 Parametric Equalizer control
1801*******************************/
1802u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys,
1803 u32 h_control, u16 *pw_number_of_bands, u16 *pw_enabled);
1804
1805u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys,
1806 u32 h_control, u16 on_off);
1807
1808u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
1809 u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100,
1810 short gain0_01dB);
1811
1812u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
1813 u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz,
1814 short *pnQ100, short *pn_gain0_01dB);
1815
1816u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
1817 u32 h_control, u16 index, short coeffs[5]
1818 );
1819
1820/*******************************
1821 Compressor Expander control
1822*******************************/
1823
1824u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1825 u16 attack, u16 decay, short ratio100, short threshold0_01dB,
1826 short makeup_gain0_01dB);
1827
1828u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1829 u16 *pw_attack, u16 *pw_decay, short *pw_ratio100,
1830 short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB);
1831
1832/*******************************
1833 Cobranet HMI control
1834*******************************/
1835u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1836 u32 hmi_address, u32 byte_count, u8 *pb_data);
1837
1838u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1839 u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data);
1840
1841u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
1842 u32 h_control, u32 *pstatus, u32 *preadable_size,
1843 u32 *pwriteable_size);
1844
1845/*Read the current IP address
1846*/
1847u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
1848 u32 h_control, u32 *pi_paddress);
1849
1850/* Write the current IP address
1851*/
1852u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys,
1853 u32 h_control, u32 i_paddress);
1854
1855/* Read the static IP address
1856*/
1857u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
1858 u32 h_control, u32 *pi_paddress);
1859
1860/* Write the static IP address
1861*/
1862u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
1863 u32 h_control, u32 i_paddress);
1864
1865/* Read the MAC address
1866*/
1867u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
1868 u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs);
1869
1870/*******************************
1871 Tone Detector control
1872*******************************/
1873u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, u32 hC,
1874 u32 *state);
1875
1876u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, u32 hC,
1877 u32 enable);
1878
1879u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, u32 hC,
1880 u32 *enable);
1881
1882u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
1883 u32 hC, u32 event_enable);
1884
1885u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
1886 u32 hC, u32 *event_enable);
1887
1888u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
1889 u32 hC, int threshold);
1890
1891u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
1892 u32 hC, int *threshold);
1893
1894u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
1895 u32 hC, u32 index, u32 *frequency);
1896
1897/*******************************
1898 Silence Detector control
1899*******************************/
1900u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
1901 u32 hC, u32 *state);
1902
1903u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
1904 u32 hC, u32 enable);
1905
1906u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
1907 u32 hC, u32 *enable);
1908
1909u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
1910 u32 hC, u32 event_enable);
1911
1912u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
1913 u32 hC, u32 *event_enable);
1914
1915u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
1916 u32 hC, u32 delay);
1917
1918u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
1919 u32 hC, u32 *delay);
1920
1921u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
1922 u32 hC, int threshold);
1923
1924u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
1925 u32 hC, int *threshold);
1926
1927/*******************************
1928 Universal control
1929*******************************/
1930u16 hpi_entity_find_next(struct hpi_entity *container_entity,
1931 enum e_entity_type type, enum e_entity_role role, int recursive_flag,
1932 struct hpi_entity **current_match);
1933
1934u16 hpi_entity_copy_value_from(struct hpi_entity *entity,
1935 enum e_entity_type type, size_t item_count, void *value_dst_p);
1936
1937u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type,
1938 size_t *items, enum e_entity_role *role, void **value);
1939
1940u16 hpi_entity_alloc_and_pack(const enum e_entity_type type,
1941 const size_t item_count, const enum e_entity_role role, void *value,
1942 struct hpi_entity **entity);
1943
1944void hpi_entity_free(struct hpi_entity *entity);
1945
1946u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC,
1947 struct hpi_entity **info);
1948
1949u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC,
1950 struct hpi_entity **value);
1951
1952u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC,
1953 struct hpi_entity *value);
1954
1955/*/////////// */
1956/* DSP CLOCK */
1957/*/////////// */
1958u16 hpi_clock_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1959 u32 *ph_dsp_clock);
1960
1961u16 hpi_clock_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock,
1962 u16 hour, u16 minute, u16 second, u16 milli_second);
1963
1964u16 hpi_clock_get_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock,
1965 u16 *pw_hour, u16 *pw_minute, u16 *pw_second, u16 *pw_milli_second);
1966
1967/*/////////// */
1968/* PROFILE */
1969/*/////////// */
1970u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys,
1971 u16 adapter_index, u16 profile_index, u32 *ph_profile,
1972 u16 *pw_max_profiles);
1973
1974u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
1975 u16 index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count,
1976 u32 *pmax_micro_seconds, u32 *pmin_micro_seconds);
1977
1978u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile);
1979
1980u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile);
1981
1982u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
1983 u16 index, char *sz_profile_name, u16 profile_name_length);
1984
1985u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys,
1986 u32 h_profile, u32 *putilization);
1987
1988/*//////////////////// */
1989/* UTILITY functions */
1990
1991u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
1992 u32 sample_rate, u32 bit_rate, u32 attributes);
1993
1994/* Until it's verified, this function is for Windows OSs only */
1995
1996#endif /*_H_HPI_ */
1997/*
1998///////////////////////////////////////////////////////////////////////////////
1999// See CVS for history. Last complete set in rev 1.146
2000////////////////////////////////////////////////////////////////////////////////
2001*/
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
new file mode 100644
index 000000000000..9c50931731a5
--- /dev/null
+++ b/sound/pci/asihpi/hpi6000.c
@@ -0,0 +1,1841 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Hardware Programming Interface (HPI) for AudioScience ASI6200 series adapters.
20 These PCI bus adapters are based on the TI C6711 DSP.
21
22 Exported functions:
23 void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
24
25 #defines
26 HIDE_PCI_ASSERTS to show the PCI asserts
27 PROFILE_DSP2 get profile data from DSP2 if present (instead of DSP 1)
28
29(C) Copyright AudioScience Inc. 1998-2003
30*******************************************************************************/
31#define SOURCEFILE_NAME "hpi6000.c"
32
33#include "hpi_internal.h"
34#include "hpimsginit.h"
35#include "hpidebug.h"
36#include "hpi6000.h"
37#include "hpidspcd.h"
38#include "hpicmn.h"
39
40#define HPI_HIF_BASE (0x00000200) /* start of C67xx internal RAM */
41#define HPI_HIF_ADDR(member) \
42 (HPI_HIF_BASE + offsetof(struct hpi_hif_6000, member))
43#define HPI_HIF_ERROR_MASK 0x4000
44
45/* HPI6000 specific error codes */
46
47#define HPI6000_ERROR_BASE 900
48#define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901
49#define HPI6000_ERROR_MSG_RESP_SEND_MSG_ACK 902
50#define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903
51#define HPI6000_ERROR_MSG_GET_ADR 904
52#define HPI6000_ERROR_RESP_GET_ADR 905
53#define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906
54#define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907
55#define HPI6000_ERROR_MSG_INVALID_DSP_INDEX 908
56#define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909
57
58#define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911
59#define HPI6000_ERROR_SEND_DATA_ACK 912
60#define HPI6000_ERROR_SEND_DATA_ADR 913
61#define HPI6000_ERROR_SEND_DATA_TIMEOUT 914
62#define HPI6000_ERROR_SEND_DATA_CMD 915
63#define HPI6000_ERROR_SEND_DATA_WRITE 916
64#define HPI6000_ERROR_SEND_DATA_IDLECMD 917
65#define HPI6000_ERROR_SEND_DATA_VERIFY 918
66
67#define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921
68#define HPI6000_ERROR_GET_DATA_ACK 922
69#define HPI6000_ERROR_GET_DATA_CMD 923
70#define HPI6000_ERROR_GET_DATA_READ 924
71#define HPI6000_ERROR_GET_DATA_IDLECMD 925
72
73#define HPI6000_ERROR_CONTROL_CACHE_ADDRLEN 951
74#define HPI6000_ERROR_CONTROL_CACHE_READ 952
75#define HPI6000_ERROR_CONTROL_CACHE_FLUSH 953
76
77#define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961
78#define HPI6000_ERROR_MSG_RESP_IDLECMD 962
79#define HPI6000_ERROR_MSG_RESP_BLOCKVERIFY32 963
80
81/* adapter init errors */
82#define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930
83
84/* can't access PCI2040 */
85#define HPI6000_ERROR_INIT_PCI2040 931
86/* can't access DSP HPI i/f */
87#define HPI6000_ERROR_INIT_DSPHPI 932
88/* can't access internal DSP memory */
89#define HPI6000_ERROR_INIT_DSPINTMEM 933
90/* can't access SDRAM - test#1 */
91#define HPI6000_ERROR_INIT_SDRAM1 934
92/* can't access SDRAM - test#2 */
93#define HPI6000_ERROR_INIT_SDRAM2 935
94
95#define HPI6000_ERROR_INIT_VERIFY 938
96
97#define HPI6000_ERROR_INIT_NOACK 939
98
99#define HPI6000_ERROR_INIT_PLDTEST1 941
100#define HPI6000_ERROR_INIT_PLDTEST2 942
101
102/* local defines */
103
104#define HIDE_PCI_ASSERTS
105#define PROFILE_DSP2
106
107/* for PCI2040 i/f chip */
108/* HPI CSR registers */
109/* word offsets from CSR base */
110/* use when io addresses defined as u32 * */
111
112#define INTERRUPT_EVENT_SET 0
113#define INTERRUPT_EVENT_CLEAR 1
114#define INTERRUPT_MASK_SET 2
115#define INTERRUPT_MASK_CLEAR 3
116#define HPI_ERROR_REPORT 4
117#define HPI_RESET 5
118#define HPI_DATA_WIDTH 6
119
120#define MAX_DSPS 2
121/* HPI registers, spaced 8K bytes = 2K words apart */
122#define DSP_SPACING 0x800
123
124#define CONTROL 0x0000
125#define ADDRESS 0x0200
126#define DATA_AUTOINC 0x0400
127#define DATA 0x0600
128
129#define TIMEOUT 500000
130
131struct dsp_obj {
132 __iomem u32 *prHPI_control;
133 __iomem u32 *prHPI_address;
134 __iomem u32 *prHPI_data;
135 __iomem u32 *prHPI_data_auto_inc;
136 char c_dsp_rev; /*A, B */
137 u32 control_cache_address_on_dsp;
138 u32 control_cache_length_on_dsp;
139 struct hpi_adapter_obj *pa_parent_adapter;
140};
141
142struct hpi_hw_obj {
143 __iomem u32 *dw2040_HPICSR;
144 __iomem u32 *dw2040_HPIDSP;
145
146 u16 num_dsp;
147 struct dsp_obj ado[MAX_DSPS];
148
149 u32 message_buffer_address_on_dsp;
150 u32 response_buffer_address_on_dsp;
151 u32 pCI2040HPI_error_count;
152
153 struct hpi_control_cache_single control_cache[HPI_NMIXER_CONTROLS];
154 struct hpi_control_cache *p_cache;
155};
156
157static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
158 u16 dsp_index, u32 hpi_address, u32 *source, u32 count);
159static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
160 u16 dsp_index, u32 hpi_address, u32 *dest, u32 count);
161
162static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
163 u32 *pos_error_code);
164static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
165 u16 read_or_write);
166#define H6READ 1
167#define H6WRITE 0
168
169static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
170 struct hpi_message *phm);
171static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
172 u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr);
173
174static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
175 struct hpi_response *phr);
176
177static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
178 u32 ack_value);
179
180static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
181 u16 dsp_index, u32 host_cmd);
182
183static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo);
184
185static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
186 struct hpi_message *phm, struct hpi_response *phr);
187
188static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
189 struct hpi_message *phm, struct hpi_response *phr);
190
191static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data);
192
193static u32 hpi_read_word(struct dsp_obj *pdo, u32 address);
194
195static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
196 u32 length);
197
198static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
199 u32 length);
200
201static void subsys_create_adapter(struct hpi_message *phm,
202 struct hpi_response *phr);
203
204static void subsys_delete_adapter(struct hpi_message *phm,
205 struct hpi_response *phr);
206
207static void adapter_get_asserts(struct hpi_adapter_obj *pao,
208 struct hpi_message *phm, struct hpi_response *phr);
209
210static short create_adapter_obj(struct hpi_adapter_obj *pao,
211 u32 *pos_error_code);
212
213/* local globals */
214
215static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */
216static u16 gw_pci_write_asserts; /* used to count PCI2040 errors */
217
218static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
219{
220
221 switch (phm->function) {
222 case HPI_SUBSYS_OPEN:
223 case HPI_SUBSYS_CLOSE:
224 case HPI_SUBSYS_GET_INFO:
225 case HPI_SUBSYS_DRIVER_UNLOAD:
226 case HPI_SUBSYS_DRIVER_LOAD:
227 case HPI_SUBSYS_FIND_ADAPTERS:
228 /* messages that should not get here */
229 phr->error = HPI_ERROR_UNIMPLEMENTED;
230 break;
231 case HPI_SUBSYS_CREATE_ADAPTER:
232 subsys_create_adapter(phm, phr);
233 break;
234 case HPI_SUBSYS_DELETE_ADAPTER:
235 subsys_delete_adapter(phm, phr);
236 break;
237 default:
238 phr->error = HPI_ERROR_INVALID_FUNC;
239 break;
240 }
241}
242
243static void control_message(struct hpi_adapter_obj *pao,
244 struct hpi_message *phm, struct hpi_response *phr)
245{
246
247 switch (phm->function) {
248 case HPI_CONTROL_GET_STATE:
249 if (pao->has_control_cache) {
250 u16 err;
251 err = hpi6000_update_control_cache(pao, phm);
252
253 if (err) {
254 phr->error = err;
255 break;
256 }
257
258 if (hpi_check_control_cache(((struct hpi_hw_obj *)
259 pao->priv)->p_cache, phm,
260 phr))
261 break;
262 }
263 hw_message(pao, phm, phr);
264 break;
265 case HPI_CONTROL_GET_INFO:
266 hw_message(pao, phm, phr);
267 break;
268 case HPI_CONTROL_SET_STATE:
269 hw_message(pao, phm, phr);
270 hpi_sync_control_cache(((struct hpi_hw_obj *)pao->priv)->
271 p_cache, phm, phr);
272 break;
273 default:
274 phr->error = HPI_ERROR_INVALID_FUNC;
275 break;
276 }
277}
278
279static void adapter_message(struct hpi_adapter_obj *pao,
280 struct hpi_message *phm, struct hpi_response *phr)
281{
282 switch (phm->function) {
283 case HPI_ADAPTER_GET_INFO:
284 hw_message(pao, phm, phr);
285 break;
286 case HPI_ADAPTER_GET_ASSERT:
287 adapter_get_asserts(pao, phm, phr);
288 break;
289 case HPI_ADAPTER_OPEN:
290 case HPI_ADAPTER_CLOSE:
291 case HPI_ADAPTER_TEST_ASSERT:
292 case HPI_ADAPTER_SELFTEST:
293 case HPI_ADAPTER_GET_MODE:
294 case HPI_ADAPTER_SET_MODE:
295 case HPI_ADAPTER_FIND_OBJECT:
296 case HPI_ADAPTER_GET_PROPERTY:
297 case HPI_ADAPTER_SET_PROPERTY:
298 case HPI_ADAPTER_ENUM_PROPERTY:
299 hw_message(pao, phm, phr);
300 break;
301 default:
302 phr->error = HPI_ERROR_INVALID_FUNC;
303 break;
304 }
305}
306
307static void outstream_message(struct hpi_adapter_obj *pao,
308 struct hpi_message *phm, struct hpi_response *phr)
309{
310 switch (phm->function) {
311 case HPI_OSTREAM_HOSTBUFFER_ALLOC:
312 case HPI_OSTREAM_HOSTBUFFER_FREE:
313 /* Don't let these messages go to the HW function because
314 * they're called without allocating the spinlock.
315 * For the HPI6000 adapters the HW would return
316 * HPI_ERROR_INVALID_FUNC anyway.
317 */
318 phr->error = HPI_ERROR_INVALID_FUNC;
319 break;
320 default:
321 hw_message(pao, phm, phr);
322 return;
323 }
324}
325
326static void instream_message(struct hpi_adapter_obj *pao,
327 struct hpi_message *phm, struct hpi_response *phr)
328{
329
330 switch (phm->function) {
331 case HPI_ISTREAM_HOSTBUFFER_ALLOC:
332 case HPI_ISTREAM_HOSTBUFFER_FREE:
333 /* Don't let these messages go to the HW function because
334 * they're called without allocating the spinlock.
335 * For the HPI6000 adapters the HW would return
336 * HPI_ERROR_INVALID_FUNC anyway.
337 */
338 phr->error = HPI_ERROR_INVALID_FUNC;
339 break;
340 default:
341 hw_message(pao, phm, phr);
342 return;
343 }
344}
345
346/************************************************************************/
347/** HPI_6000()
348 * Entry point from HPIMAN
349 * All calls to the HPI start here
350 */
351void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
352{
353 struct hpi_adapter_obj *pao = NULL;
354
355 /* subsytem messages get executed by every HPI. */
356 /* All other messages are ignored unless the adapter index matches */
357 /* an adapter in the HPI */
358 HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->object, phm->function);
359
360 /* if Dsp has crashed then do not communicate with it any more */
361 if (phm->object != HPI_OBJ_SUBSYSTEM) {
362 pao = hpi_find_adapter(phm->adapter_index);
363 if (!pao) {
364 HPI_DEBUG_LOG(DEBUG,
365 " %d,%d refused, for another HPI?\n",
366 phm->object, phm->function);
367 return;
368 }
369
370 if (pao->dsp_crashed >= 10) {
371 hpi_init_response(phr, phm->object, phm->function,
372 HPI_ERROR_DSP_HARDWARE);
373 HPI_DEBUG_LOG(DEBUG, " %d,%d dsp crashed.\n",
374 phm->object, phm->function);
375 return;
376 }
377 }
378 /* Init default response including the size field */
379 if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
380 hpi_init_response(phr, phm->object, phm->function,
381 HPI_ERROR_PROCESSING_MESSAGE);
382
383 switch (phm->type) {
384 case HPI_TYPE_MESSAGE:
385 switch (phm->object) {
386 case HPI_OBJ_SUBSYSTEM:
387 subsys_message(phm, phr);
388 break;
389
390 case HPI_OBJ_ADAPTER:
391 phr->size =
392 sizeof(struct hpi_response_header) +
393 sizeof(struct hpi_adapter_res);
394 adapter_message(pao, phm, phr);
395 break;
396
397 case HPI_OBJ_CONTROL:
398 control_message(pao, phm, phr);
399 break;
400
401 case HPI_OBJ_OSTREAM:
402 outstream_message(pao, phm, phr);
403 break;
404
405 case HPI_OBJ_ISTREAM:
406 instream_message(pao, phm, phr);
407 break;
408
409 default:
410 hw_message(pao, phm, phr);
411 break;
412 }
413 break;
414
415 default:
416 phr->error = HPI_ERROR_INVALID_TYPE;
417 break;
418 }
419}
420
421/************************************************************************/
422/* SUBSYSTEM */
423
424/* create an adapter object and initialise it based on resource information
425 * passed in in the message
426 * NOTE - you cannot use this function AND the FindAdapters function at the
427 * same time, the application must use only one of them to get the adapters
428 */
429static void subsys_create_adapter(struct hpi_message *phm,
430 struct hpi_response *phr)
431{
432 /* create temp adapter obj, because we don't know what index yet */
433 struct hpi_adapter_obj ao;
434 struct hpi_adapter_obj *pao;
435 u32 os_error_code;
436 short error = 0;
437 u32 dsp_index = 0;
438
439 HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");
440
441 memset(&ao, 0, sizeof(ao));
442
443 /* this HPI only creates adapters for TI/PCI2040 based devices */
444 if (phm->u.s.resource.bus_type != HPI_BUS_PCI)
445 return;
446 if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI)
447 return;
448 if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040)
449 return;
450
451 ao.priv = kmalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
452 if (!ao.priv) {
453 HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
454 phr->error = HPI_ERROR_MEMORY_ALLOC;
455 return;
456 }
457
458 memset(ao.priv, 0, sizeof(struct hpi_hw_obj));
459 /* create the adapter object based on the resource information */
460 /*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */
461 ao.pci = *phm->u.s.resource.r.pci;
462
463 error = create_adapter_obj(&ao, &os_error_code);
464 if (!error)
465 error = hpi_add_adapter(&ao);
466 if (error) {
467 phr->u.s.data = os_error_code;
468 kfree(ao.priv);
469 phr->error = error;
470 return;
471 }
472 /* need to update paParentAdapter */
473 pao = hpi_find_adapter(ao.index);
474 if (!pao) {
475 /* We just added this adapter, why can't we find it!? */
476 HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
477 phr->error = 950;
478 return;
479 }
480
481 for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
482 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
483 phw->ado[dsp_index].pa_parent_adapter = pao;
484 }
485
486 phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
487 phr->u.s.adapter_index = ao.index;
488 phr->u.s.num_adapters++;
489 phr->error = 0;
490}
491
492static void subsys_delete_adapter(struct hpi_message *phm,
493 struct hpi_response *phr)
494{
495 struct hpi_adapter_obj *pao = NULL;
496 struct hpi_hw_obj *phw;
497
498 pao = hpi_find_adapter(phm->adapter_index);
499 if (!pao)
500 return;
501
502 phw = (struct hpi_hw_obj *)pao->priv;
503
504 if (pao->has_control_cache)
505 hpi_free_control_cache(phw->p_cache);
506
507 hpi_delete_adapter(pao);
508 kfree(phw);
509
510 phr->error = 0;
511}
512
513/* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */
514static short create_adapter_obj(struct hpi_adapter_obj *pao,
515 u32 *pos_error_code)
516{
517 short boot_error = 0;
518 u32 dsp_index = 0;
519 u32 control_cache_size = 0;
520 u32 control_cache_count = 0;
521 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
522
523 /* init error reporting */
524 pao->dsp_crashed = 0;
525
526 /* The PCI2040 has the following address map */
527 /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
528 /* BAR1 - 32K = HPI registers on DSP */
529 phw->dw2040_HPICSR = pao->pci.ap_mem_base[0];
530 phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1];
531 HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR,
532 phw->dw2040_HPIDSP);
533
534 /* set addresses for the possible DSP HPI interfaces */
535 for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
536 phw->ado[dsp_index].prHPI_control =
537 phw->dw2040_HPIDSP + (CONTROL +
538 DSP_SPACING * dsp_index);
539
540 phw->ado[dsp_index].prHPI_address =
541 phw->dw2040_HPIDSP + (ADDRESS +
542 DSP_SPACING * dsp_index);
543 phw->ado[dsp_index].prHPI_data =
544 phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index);
545
546 phw->ado[dsp_index].prHPI_data_auto_inc =
547 phw->dw2040_HPIDSP + (DATA_AUTOINC +
548 DSP_SPACING * dsp_index);
549
550 HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n",
551 phw->ado[dsp_index].prHPI_control,
552 phw->ado[dsp_index].prHPI_address,
553 phw->ado[dsp_index].prHPI_data,
554 phw->ado[dsp_index].prHPI_data_auto_inc);
555
556 phw->ado[dsp_index].pa_parent_adapter = pao;
557 }
558
559 phw->pCI2040HPI_error_count = 0;
560 pao->has_control_cache = 0;
561
562 /* Set the default number of DSPs on this card */
563 /* This is (conditionally) adjusted after bootloading */
564 /* of the first DSP in the bootload section. */
565 phw->num_dsp = 1;
566
567 boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code);
568 if (boot_error)
569 return boot_error;
570
571 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
572
573 phw->message_buffer_address_on_dsp = 0L;
574 phw->response_buffer_address_on_dsp = 0L;
575
576 /* get info about the adapter by asking the adapter */
577 /* send a HPI_ADAPTER_GET_INFO message */
578 {
579 struct hpi_message hM;
580 struct hpi_response hR0; /* response from DSP 0 */
581 struct hpi_response hR1; /* response from DSP 1 */
582 u16 error = 0;
583
584 HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
585 memset(&hM, 0, sizeof(hM));
586 hM.type = HPI_TYPE_MESSAGE;
587 hM.size = sizeof(struct hpi_message);
588 hM.object = HPI_OBJ_ADAPTER;
589 hM.function = HPI_ADAPTER_GET_INFO;
590 hM.adapter_index = 0;
591 memset(&hR0, 0, sizeof(hR0));
592 memset(&hR1, 0, sizeof(hR1));
593 hR0.size = sizeof(hR0);
594 hR1.size = sizeof(hR1);
595
596 error = hpi6000_message_response_sequence(pao, 0, &hM, &hR0);
597 if (hR0.error) {
598 HPI_DEBUG_LOG(DEBUG, "message error %d\n", hR0.error);
599 return hR0.error;
600 }
601 if (phw->num_dsp == 2) {
602 error = hpi6000_message_response_sequence(pao, 1, &hM,
603 &hR1);
604 if (error)
605 return error;
606 }
607 pao->adapter_type = hR0.u.a.adapter_type;
608 pao->index = hR0.u.a.adapter_index;
609 }
610
611 memset(&phw->control_cache[0], 0,
612 sizeof(struct hpi_control_cache_single) *
613 HPI_NMIXER_CONTROLS);
614 /* Read the control cache length to figure out if it is turned on */
615 control_cache_size =
616 hpi_read_word(&phw->ado[0],
617 HPI_HIF_ADDR(control_cache_size_in_bytes));
618 if (control_cache_size) {
619 control_cache_count =
620 hpi_read_word(&phw->ado[0],
621 HPI_HIF_ADDR(control_cache_count));
622 pao->has_control_cache = 1;
623
624 phw->p_cache =
625 hpi_alloc_control_cache(control_cache_count,
626 control_cache_size, (struct hpi_control_cache_info *)
627 &phw->control_cache[0]
628 );
629 } else
630 pao->has_control_cache = 0;
631
632 HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n",
633 pao->adapter_type, pao->index);
634 pao->open = 0; /* upon creation the adapter is closed */
635 return 0;
636}
637
638/************************************************************************/
639/* ADAPTER */
640
641static void adapter_get_asserts(struct hpi_adapter_obj *pao,
642 struct hpi_message *phm, struct hpi_response *phr)
643{
644#ifndef HIDE_PCI_ASSERTS
645 /* if we have PCI2040 asserts then collect them */
646 if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
647 phr->u.a.serial_number =
648 gw_pci_read_asserts * 100 + gw_pci_write_asserts;
649 phr->u.a.adapter_index = 1; /* assert count */
650 phr->u.a.adapter_type = -1; /* "dsp index" */
651 strcpy(phr->u.a.sz_adapter_assert, "PCI2040 error");
652 gw_pci_read_asserts = 0;
653 gw_pci_write_asserts = 0;
654 phr->error = 0;
655 } else
656#endif
657 hw_message(pao, phm, phr); /*get DSP asserts */
658
659 return;
660}
661
662/************************************************************************/
663/* LOW-LEVEL */
664
665static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
666 u32 *pos_error_code)
667{
668 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
669 short error;
670 u32 timeout;
671 u32 read = 0;
672 u32 i = 0;
673 u32 data = 0;
674 u32 j = 0;
675 u32 test_addr = 0x80000000;
676 u32 test_data = 0x00000001;
677 u32 dw2040_reset = 0;
678 u32 dsp_index = 0;
679 u32 endian = 0;
680 u32 adapter_info = 0;
681 u32 delay = 0;
682
683 struct dsp_code dsp_code;
684 u16 boot_load_family = 0;
685
686 /* NOTE don't use wAdapterType in this routine. It is not setup yet */
687
688 switch (pao->pci.subsys_device_id) {
689 case 0x5100:
690 case 0x5110: /* ASI5100 revB or higher with C6711D */
691 case 0x6100:
692 case 0x6200:
693 boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
694 break;
695 case 0x8800:
696 boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x8800);
697 break;
698 default:
699 return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
700 }
701
702 /* reset all DSPs, indicate two DSPs are present
703 * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode
704 */
705 endian = 0;
706 dw2040_reset = 0x0003000F;
707 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
708
709 /* read back register to make sure PCI2040 chip is functioning
710 * note that bits 4..15 are read-only and so should always return zero,
711 * even though we wrote 1 to them
712 */
713 for (i = 0; i < 1000; i++)
714 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
715 if (delay != dw2040_reset) {
716 HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
717 delay);
718 return HPI6000_ERROR_INIT_PCI2040;
719 }
720
721 /* Indicate that DSP#0,1 is a C6X */
722 iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH);
723 /* set Bit30 and 29 - which will prevent Target aborts from being
724 * issued upon HPI or GP error
725 */
726 iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET);
727
728 /* isolate DSP HAD8 line from PCI2040 so that
729 * Little endian can be set by pullup
730 */
731 dw2040_reset = dw2040_reset & (~(endian << 3));
732 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
733
734 phw->ado[0].c_dsp_rev = 'B'; /* revB */
735 phw->ado[1].c_dsp_rev = 'B'; /* revB */
736
737 /*Take both DSPs out of reset, setting HAD8 to the correct Endian */
738 dw2040_reset = dw2040_reset & (~0x00000001); /* start DSP 0 */
739 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
740 dw2040_reset = dw2040_reset & (~0x00000002); /* start DSP 1 */
741 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
742
743 /* set HAD8 back to PCI2040, now that DSP set to little endian mode */
744 dw2040_reset = dw2040_reset & (~0x00000008);
745 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
746 /*delay to allow DSP to get going */
747 for (i = 0; i < 100; i++)
748 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
749
750 /* loop through all DSPs, downloading DSP code */
751 for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
752 struct dsp_obj *pdo = &phw->ado[dsp_index];
753
754 /* configure DSP so that we download code into the SRAM */
755 /* set control reg for little endian, HWOB=1 */
756 iowrite32(0x00010001, pdo->prHPI_control);
757
758 /* test access to the HPI address register (HPIA) */
759 test_data = 0x00000001;
760 for (j = 0; j < 32; j++) {
761 iowrite32(test_data, pdo->prHPI_address);
762 data = ioread32(pdo->prHPI_address);
763 if (data != test_data) {
764 HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n",
765 test_data, data, dsp_index);
766 return HPI6000_ERROR_INIT_DSPHPI;
767 }
768 test_data = test_data << 1;
769 }
770
771/* if C6713 the setup PLL to generate 225MHz from 25MHz.
772* Since the PLLDIV1 read is sometimes wrong, even on a C6713,
773* we're going to do this unconditionally
774*/
775/* PLLDIV1 should have a value of 8000 after reset */
776/*
777 if (HpiReadWord(pdo,0x01B7C118) == 0x8000)
778*/
779 {
780 /* C6713 datasheet says we cannot program PLL from HPI,
781 * and indeed if we try to set the PLL multiply from the
782 * HPI, the PLL does not seem to lock,
783 * so we enable the PLL and use the default of x 7
784 */
785 /* bypass PLL */
786 hpi_write_word(pdo, 0x01B7C100, 0x0000);
787 for (i = 0; i < 100; i++)
788 delay = ioread32(phw->dw2040_HPICSR +
789 HPI_RESET);
790
791 /* ** use default of PLL x7 ** */
792 /* EMIF = 225/3=75MHz */
793 hpi_write_word(pdo, 0x01B7C120, 0x8002);
794 /* peri = 225/2 */
795 hpi_write_word(pdo, 0x01B7C11C, 0x8001);
796 /* cpu = 225/1 */
797 hpi_write_word(pdo, 0x01B7C118, 0x8000);
798 /* ~200us delay */
799 for (i = 0; i < 2000; i++)
800 delay = ioread32(phw->dw2040_HPICSR +
801 HPI_RESET);
802 /* PLL not bypassed */
803 hpi_write_word(pdo, 0x01B7C100, 0x0001);
804 /* ~200us delay */
805 for (i = 0; i < 2000; i++)
806 delay = ioread32(phw->dw2040_HPICSR +
807 HPI_RESET);
808 }
809
810 /* test r/w to internal DSP memory
811 * C6711 has L2 cache mapped to 0x0 when reset
812 *
813 * revB - because of bug 3.0.1 last HPI read
814 * (before HPI address issued) must be non-autoinc
815 */
816 /* test each bit in the 32bit word */
817 for (i = 0; i < 100; i++) {
818 test_addr = 0x00000000;
819 test_data = 0x00000001;
820 for (j = 0; j < 32; j++) {
821 hpi_write_word(pdo, test_addr + i, test_data);
822 data = hpi_read_word(pdo, test_addr + i);
823 if (data != test_data) {
824 HPI_DEBUG_LOG(ERROR,
825 "DSP mem %x %x %x %x\n",
826 test_addr + i, test_data,
827 data, dsp_index);
828
829 return HPI6000_ERROR_INIT_DSPINTMEM;
830 }
831 test_data = test_data << 1;
832 }
833 }
834
835 /* memory map of ASI6200
836 00000000-0000FFFF 16Kx32 internal program
837 01800000-019FFFFF Internal peripheral
838 80000000-807FFFFF CE0 2Mx32 SDRAM running @ 100MHz
839 90000000-9000FFFF CE1 Async peripherals:
840
841 EMIF config
842 ------------
843 Global EMIF control
844 0 -
845 1 -
846 2 -
847 3 CLK2EN = 1 CLKOUT2 enabled
848 4 CLK1EN = 0 CLKOUT1 disabled
849 5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT
850 6 -
851 7 NOHOLD = 1 external HOLD disabled
852 8 HOLDA = 0 HOLDA output is low
853 9 HOLD = 0 HOLD input is low
854 10 ARDY = 1 ARDY input is high
855 11 BUSREQ = 0 BUSREQ output is low
856 12,13 Reserved = 1
857 */
858 hpi_write_word(pdo, 0x01800000, 0x34A8);
859
860 /* EMIF CE0 setup - 2Mx32 Sync DRAM
861 31..28 Wr setup
862 27..22 Wr strobe
863 21..20 Wr hold
864 19..16 Rd setup
865 15..14 -
866 13..8 Rd strobe
867 7..4 MTYPE 0011 Sync DRAM 32bits
868 3 Wr hold MSB
869 2..0 Rd hold
870 */
871 hpi_write_word(pdo, 0x01800008, 0x00000030);
872
873 /* EMIF SDRAM Extension
874 31-21 0
875 20 WR2RD = 0
876 19-18 WR2DEAC = 1
877 17 WR2WR = 0
878 16-15 R2WDQM = 2
879 14-12 RD2WR = 4
880 11-10 RD2DEAC = 1
881 9 RD2RD = 1
882 8-7 THZP = 10b
883 6-5 TWR = 2-1 = 01b (tWR = 10ns)
884 4 TRRD = 0b = 2 ECLK (tRRD = 14ns)
885 3-1 TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK)
886 1 CAS latency = 3 ECLK
887 (for Micron 2M32-7 operating at 100Mhz)
888 */
889
890 /* need to use this else DSP code crashes */
891 hpi_write_word(pdo, 0x01800020, 0x001BDF29);
892
893 /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
894 31 - -
895 30 SDBSZ 1 4 bank
896 29..28 SDRSZ 00 11 row address pins
897 27..26 SDCSZ 01 8 column address pins
898 25 RFEN 1 refersh enabled
899 24 INIT 1 init SDRAM
900 23..20 TRCD 0001
901 19..16 TRP 0001
902 15..12 TRC 0110
903 11..0 - -
904 */
905 /* need to use this else DSP code crashes */
906 hpi_write_word(pdo, 0x01800018, 0x47117000);
907
908 /* EMIF SDRAM Refresh Timing */
909 hpi_write_word(pdo, 0x0180001C, 0x00000410);
910
911 /*MIF CE1 setup - Async peripherals
912 @100MHz bus speed, each cycle is 10ns,
913 31..28 Wr setup = 1
914 27..22 Wr strobe = 3 30ns
915 21..20 Wr hold = 1
916 19..16 Rd setup =1
917 15..14 Ta = 2
918 13..8 Rd strobe = 3 30ns
919 7..4 MTYPE 0010 Async 32bits
920 3 Wr hold MSB =0
921 2..0 Rd hold = 1
922 */
923 {
924 u32 cE1 =
925 (1L << 28) | (3L << 22) | (1L << 20) | (1L <<
926 16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L;
927 hpi_write_word(pdo, 0x01800004, cE1);
928 }
929
930 /* delay a little to allow SDRAM and DSP to "get going" */
931
932 for (i = 0; i < 1000; i++)
933 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
934
935 /* test access to SDRAM */
936 {
937 test_addr = 0x80000000;
938 test_data = 0x00000001;
939 /* test each bit in the 32bit word */
940 for (j = 0; j < 32; j++) {
941 hpi_write_word(pdo, test_addr, test_data);
942 data = hpi_read_word(pdo, test_addr);
943 if (data != test_data) {
944 HPI_DEBUG_LOG(ERROR,
945 "DSP dram %x %x %x %x\n",
946 test_addr, test_data, data,
947 dsp_index);
948
949 return HPI6000_ERROR_INIT_SDRAM1;
950 }
951 test_data = test_data << 1;
952 }
953 /* test every Nth address in the DRAM */
954#define DRAM_SIZE_WORDS 0x200000 /*2_mx32 */
955#define DRAM_INC 1024
956 test_addr = 0x80000000;
957 test_data = 0x0;
958 for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
959 hpi_write_word(pdo, test_addr + i, test_data);
960 test_data++;
961 }
962 test_addr = 0x80000000;
963 test_data = 0x0;
964 for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
965 data = hpi_read_word(pdo, test_addr + i);
966 if (data != test_data) {
967 HPI_DEBUG_LOG(ERROR,
968 "DSP dram %x %x %x %x\n",
969 test_addr + i, test_data,
970 data, dsp_index);
971 return HPI6000_ERROR_INIT_SDRAM2;
972 }
973 test_data++;
974 }
975
976 }
977
978 /* write the DSP code down into the DSPs memory */
979 /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */
980 dsp_code.ps_dev = pao->pci.p_os_data;
981
982 error = hpi_dsp_code_open(boot_load_family, &dsp_code,
983 pos_error_code);
984
985 if (error)
986 return error;
987
988 while (1) {
989 u32 length;
990 u32 address;
991 u32 type;
992 u32 *pcode;
993
994 error = hpi_dsp_code_read_word(&dsp_code, &length);
995 if (error)
996 break;
997 if (length == 0xFFFFFFFF)
998 break; /* end of code */
999
1000 error = hpi_dsp_code_read_word(&dsp_code, &address);
1001 if (error)
1002 break;
1003 error = hpi_dsp_code_read_word(&dsp_code, &type);
1004 if (error)
1005 break;
1006 error = hpi_dsp_code_read_block(length, &dsp_code,
1007 &pcode);
1008 if (error)
1009 break;
1010 error = hpi6000_dsp_block_write32(pao, (u16)dsp_index,
1011 address, pcode, length);
1012 if (error)
1013 break;
1014 }
1015
1016 if (error) {
1017 hpi_dsp_code_close(&dsp_code);
1018 return error;
1019 }
1020 /* verify that code was written correctly */
1021 /* this time through, assume no errors in DSP code file/array */
1022 hpi_dsp_code_rewind(&dsp_code);
1023 while (1) {
1024 u32 length;
1025 u32 address;
1026 u32 type;
1027 u32 *pcode;
1028
1029 hpi_dsp_code_read_word(&dsp_code, &length);
1030 if (length == 0xFFFFFFFF)
1031 break; /* end of code */
1032
1033 hpi_dsp_code_read_word(&dsp_code, &address);
1034 hpi_dsp_code_read_word(&dsp_code, &type);
1035 hpi_dsp_code_read_block(length, &dsp_code, &pcode);
1036
1037 for (i = 0; i < length; i++) {
1038 data = hpi_read_word(pdo, address);
1039 if (data != *pcode) {
1040 error = HPI6000_ERROR_INIT_VERIFY;
1041 HPI_DEBUG_LOG(ERROR,
1042 "DSP verify %x %x %x %x\n",
1043 address, *pcode, data,
1044 dsp_index);
1045 break;
1046 }
1047 pcode++;
1048 address += 4;
1049 }
1050 if (error)
1051 break;
1052 }
1053 hpi_dsp_code_close(&dsp_code);
1054 if (error)
1055 return error;
1056
1057 /* zero out the hostmailbox */
1058 {
1059 u32 address = HPI_HIF_ADDR(host_cmd);
1060 for (i = 0; i < 4; i++) {
1061 hpi_write_word(pdo, address, 0);
1062 address += 4;
1063 }
1064 }
1065 /* write the DSP number into the hostmailbox */
1066 /* structure before starting the DSP */
1067 hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index);
1068
1069 /* write the DSP adapter Info into the */
1070 /* hostmailbox before starting the DSP */
1071 if (dsp_index > 0)
1072 hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info),
1073 adapter_info);
1074
1075 /* step 3. Start code by sending interrupt */
1076 iowrite32(0x00030003, pdo->prHPI_control);
1077 for (i = 0; i < 10000; i++)
1078 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
1079
1080 /* wait for a non-zero value in hostcmd -
1081 * indicating initialization is complete
1082 *
1083 * Init could take a while if DSP checks SDRAM memory
1084 * Was 200000. Increased to 2000000 for ASI8801 so we
1085 * don't get 938 errors.
1086 */
1087 timeout = 2000000;
1088 while (timeout) {
1089 do {
1090 read = hpi_read_word(pdo,
1091 HPI_HIF_ADDR(host_cmd));
1092 } while (--timeout
1093 && hpi6000_check_PCI2040_error_flag(pao,
1094 H6READ));
1095
1096 if (read)
1097 break;
1098 /* The following is a workaround for bug #94:
1099 * Bluescreen on install and subsequent boots on a
1100 * DELL PowerEdge 600SC PC with 1.8GHz P4 and
1101 * ServerWorks chipset. Without this delay the system
1102 * locks up with a bluescreen (NOT GPF or pagefault).
1103 */
1104 else
1105 hpios_delay_micro_seconds(1000);
1106 }
1107 if (timeout == 0)
1108 return HPI6000_ERROR_INIT_NOACK;
1109
1110 /* read the DSP adapter Info from the */
1111 /* hostmailbox structure after starting the DSP */
1112 if (dsp_index == 0) {
1113 /*u32 dwTestData=0; */
1114 u32 mask = 0;
1115
1116 adapter_info =
1117 hpi_read_word(pdo,
1118 HPI_HIF_ADDR(adapter_info));
1119 if (HPI_ADAPTER_FAMILY_ASI
1120 (HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER
1121 (adapter_info)) ==
1122 HPI_ADAPTER_FAMILY_ASI(0x6200))
1123 /* all 6200 cards have this many DSPs */
1124 phw->num_dsp = 2;
1125
1126 /* test that the PLD is programmed */
1127 /* and we can read/write 24bits */
1128#define PLD_BASE_ADDRESS 0x90000000L /*for ASI6100/6200/8800 */
1129
1130 switch (boot_load_family) {
1131 case HPI_ADAPTER_FAMILY_ASI(0x6200):
1132 /* ASI6100/6200 has 24bit path to FPGA */
1133 mask = 0xFFFFFF00L;
1134 /* ASI5100 uses AX6 code, */
1135 /* but has no PLD r/w register to test */
1136 if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
1137 subsys_device_id) ==
1138 HPI_ADAPTER_FAMILY_ASI(0x5100))
1139 mask = 0x00000000L;
1140 break;
1141 case HPI_ADAPTER_FAMILY_ASI(0x8800):
1142 /* ASI8800 has 16bit path to FPGA */
1143 mask = 0xFFFF0000L;
1144 break;
1145 }
1146 test_data = 0xAAAAAA00L & mask;
1147 /* write to 24 bit Debug register (D31-D8) */
1148 hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1149 read = hpi_read_word(pdo,
1150 PLD_BASE_ADDRESS + 4L) & mask;
1151 if (read != test_data) {
1152 HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1153 read);
1154 return HPI6000_ERROR_INIT_PLDTEST1;
1155 }
1156 test_data = 0x55555500L & mask;
1157 hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1158 read = hpi_read_word(pdo,
1159 PLD_BASE_ADDRESS + 4L) & mask;
1160 if (read != test_data) {
1161 HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1162 read);
1163 return HPI6000_ERROR_INIT_PLDTEST2;
1164 }
1165 }
1166 } /* for numDSP */
1167 return 0;
1168}
1169
1170#define PCI_TIMEOUT 100
1171
1172static int hpi_set_address(struct dsp_obj *pdo, u32 address)
1173{
1174 u32 timeout = PCI_TIMEOUT;
1175
1176 do {
1177 iowrite32(address, pdo->prHPI_address);
1178 } while (hpi6000_check_PCI2040_error_flag(pdo->pa_parent_adapter,
1179 H6WRITE)
1180 && --timeout);
1181
1182 if (timeout)
1183 return 0;
1184
1185 return 1;
1186}
1187
1188/* write one word to the HPI port */
1189static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data)
1190{
1191 if (hpi_set_address(pdo, address))
1192 return;
1193 iowrite32(data, pdo->prHPI_data);
1194}
1195
1196/* read one word from the HPI port */
1197static u32 hpi_read_word(struct dsp_obj *pdo, u32 address)
1198{
1199 u32 data = 0;
1200
1201 if (hpi_set_address(pdo, address))
1202 return 0; /*? no way to return error */
1203
1204 /* take care of errata in revB DSP (2.0.1) */
1205 data = ioread32(pdo->prHPI_data);
1206 return data;
1207}
1208
1209/* write a block of 32bit words to the DSP HPI port using auto-inc mode */
1210static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1211 u32 length)
1212{
1213 u16 length16 = length - 1;
1214
1215 if (length == 0)
1216 return;
1217
1218 if (hpi_set_address(pdo, address))
1219 return;
1220
1221 iowrite32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1222
1223 /* take care of errata in revB DSP (2.0.1) */
1224 /* must end with non auto-inc */
1225 iowrite32(*(pdata + length - 1), pdo->prHPI_data);
1226}
1227
1228/** read a block of 32bit words from the DSP HPI port using auto-inc mode
1229 */
1230static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1231 u32 length)
1232{
1233 u16 length16 = length - 1;
1234
1235 if (length == 0)
1236 return;
1237
1238 if (hpi_set_address(pdo, address))
1239 return;
1240
1241 ioread32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1242
1243 /* take care of errata in revB DSP (2.0.1) */
1244 /* must end with non auto-inc */
1245 *(pdata + length - 1) = ioread32(pdo->prHPI_data);
1246}
1247
1248static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
1249 u16 dsp_index, u32 hpi_address, u32 *source, u32 count)
1250{
1251 struct dsp_obj *pdo =
1252 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1253 u32 time_out = PCI_TIMEOUT;
1254 int c6711_burst_size = 128;
1255 u32 local_hpi_address = hpi_address;
1256 int local_count = count;
1257 int xfer_size;
1258 u32 *pdata = source;
1259
1260 while (local_count) {
1261 if (local_count > c6711_burst_size)
1262 xfer_size = c6711_burst_size;
1263 else
1264 xfer_size = local_count;
1265
1266 time_out = PCI_TIMEOUT;
1267 do {
1268 hpi_write_block(pdo, local_hpi_address, pdata,
1269 xfer_size);
1270 } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1271 && --time_out);
1272
1273 if (!time_out)
1274 break;
1275 pdata += xfer_size;
1276 local_hpi_address += sizeof(u32) * xfer_size;
1277 local_count -= xfer_size;
1278 }
1279
1280 if (time_out)
1281 return 0;
1282 else
1283 return 1;
1284}
1285
1286static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
1287 u16 dsp_index, u32 hpi_address, u32 *dest, u32 count)
1288{
1289 struct dsp_obj *pdo =
1290 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1291 u32 time_out = PCI_TIMEOUT;
1292 int c6711_burst_size = 16;
1293 u32 local_hpi_address = hpi_address;
1294 int local_count = count;
1295 int xfer_size;
1296 u32 *pdata = dest;
1297 u32 loop_count = 0;
1298
1299 while (local_count) {
1300 if (local_count > c6711_burst_size)
1301 xfer_size = c6711_burst_size;
1302 else
1303 xfer_size = local_count;
1304
1305 time_out = PCI_TIMEOUT;
1306 do {
1307 hpi_read_block(pdo, local_hpi_address, pdata,
1308 xfer_size);
1309 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1310 && --time_out);
1311 if (!time_out)
1312 break;
1313
1314 pdata += xfer_size;
1315 local_hpi_address += sizeof(u32) * xfer_size;
1316 local_count -= xfer_size;
1317 loop_count++;
1318 }
1319
1320 if (time_out)
1321 return 0;
1322 else
1323 return 1;
1324}
1325
1326static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
1327 u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr)
1328{
1329 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
1330 struct dsp_obj *pdo = &phw->ado[dsp_index];
1331 u32 timeout;
1332 u16 ack;
1333 u32 address;
1334 u32 length;
1335 u32 *p_data;
1336 u16 error = 0;
1337
1338 /* does the DSP we are referencing exist? */
1339 if (dsp_index >= phw->num_dsp)
1340 return HPI6000_ERROR_MSG_INVALID_DSP_INDEX;
1341
1342 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1343 if (ack & HPI_HIF_ERROR_MASK) {
1344 pao->dsp_crashed++;
1345 return HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT;
1346 }
1347 pao->dsp_crashed = 0;
1348
1349 /* send the message */
1350
1351 /* get the address and size */
1352 if (phw->message_buffer_address_on_dsp == 0) {
1353 timeout = TIMEOUT;
1354 do {
1355 address =
1356 hpi_read_word(pdo,
1357 HPI_HIF_ADDR(message_buffer_address));
1358 phw->message_buffer_address_on_dsp = address;
1359 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1360 && --timeout);
1361 if (!timeout)
1362 return HPI6000_ERROR_MSG_GET_ADR;
1363 } else
1364 address = phw->message_buffer_address_on_dsp;
1365
1366 /* dwLength = sizeof(struct hpi_message); */
1367 length = phm->size;
1368
1369 /* send it */
1370 p_data = (u32 *)phm;
1371 if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
1372 (u16)length / 4))
1373 return HPI6000_ERROR_MSG_RESP_BLOCKWRITE32;
1374
1375 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_GET_RESP))
1376 return HPI6000_ERROR_MSG_RESP_GETRESPCMD;
1377 hpi6000_send_dsp_interrupt(pdo);
1378
1379 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_RESP);
1380 if (ack & HPI_HIF_ERROR_MASK)
1381 return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
1382
1383 /* get the address and size */
1384 if (phw->response_buffer_address_on_dsp == 0) {
1385 timeout = TIMEOUT;
1386 do {
1387 address =
1388 hpi_read_word(pdo,
1389 HPI_HIF_ADDR(response_buffer_address));
1390 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1391 && --timeout);
1392 phw->response_buffer_address_on_dsp = address;
1393
1394 if (!timeout)
1395 return HPI6000_ERROR_RESP_GET_ADR;
1396 } else
1397 address = phw->response_buffer_address_on_dsp;
1398
1399 /* read the length of the response back from the DSP */
1400 timeout = TIMEOUT;
1401 do {
1402 length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1403 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1404 if (!timeout)
1405 length = sizeof(struct hpi_response);
1406
1407 /* get it */
1408 p_data = (u32 *)phr;
1409 if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
1410 (u16)length / 4))
1411 return HPI6000_ERROR_MSG_RESP_BLOCKREAD32;
1412
1413 /* set i/f back to idle */
1414 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1415 return HPI6000_ERROR_MSG_RESP_IDLECMD;
1416 hpi6000_send_dsp_interrupt(pdo);
1417
1418 error = hpi_validate_response(phm, phr);
1419 return error;
1420}
1421
1422/* have to set up the below defines to match stuff in the MAP file */
1423
1424#define MSG_ADDRESS (HPI_HIF_BASE+0x18)
1425#define MSG_LENGTH 11
1426#define RESP_ADDRESS (HPI_HIF_BASE+0x44)
1427#define RESP_LENGTH 16
1428#define QUEUE_START (HPI_HIF_BASE+0x88)
1429#define QUEUE_SIZE 0x8000
1430
1431static short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords)
1432{
1433/*#define CHECKING // comment this line in to enable checking */
1434#ifdef CHECKING
1435 if (address < (u32)MSG_ADDRESS)
1436 return 0;
1437 if (address > (u32)(QUEUE_START + QUEUE_SIZE))
1438 return 0;
1439 if ((address + (length_in_dwords << 2)) >
1440 (u32)(QUEUE_START + QUEUE_SIZE))
1441 return 0;
1442#else
1443 (void)address;
1444 (void)length_in_dwords;
1445 return 1;
1446#endif
1447}
1448
1449static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1450 struct hpi_message *phm, struct hpi_response *phr)
1451{
1452 struct dsp_obj *pdo =
1453 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1454 u32 data_sent = 0;
1455 u16 ack;
1456 u32 length, address;
1457 u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1458 u16 time_out = 8;
1459
1460 (void)phr;
1461
1462 /* round dwDataSize down to nearest 4 bytes */
1463 while ((data_sent < (phm->u.d.u.data.data_size & ~3L))
1464 && --time_out) {
1465 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1466 if (ack & HPI_HIF_ERROR_MASK)
1467 return HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT;
1468
1469 if (hpi6000_send_host_command(pao, dsp_index,
1470 HPI_HIF_SEND_DATA))
1471 return HPI6000_ERROR_SEND_DATA_CMD;
1472
1473 hpi6000_send_dsp_interrupt(pdo);
1474
1475 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_SEND_DATA);
1476
1477 if (ack & HPI_HIF_ERROR_MASK)
1478 return HPI6000_ERROR_SEND_DATA_ACK;
1479
1480 do {
1481 /* get the address and size */
1482 address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1483 /* DSP returns number of DWORDS */
1484 length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1485 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1486
1487 if (!hpi6000_send_data_check_adr(address, length))
1488 return HPI6000_ERROR_SEND_DATA_ADR;
1489
1490 /* send the data. break data into 512 DWORD blocks (2K bytes)
1491 * and send using block write. 2Kbytes is the max as this is the
1492 * memory window given to the HPI data register by the PCI2040
1493 */
1494
1495 {
1496 u32 len = length;
1497 u32 blk_len = 512;
1498 while (len) {
1499 if (len < blk_len)
1500 blk_len = len;
1501 if (hpi6000_dsp_block_write32(pao, dsp_index,
1502 address, p_data, blk_len))
1503 return HPI6000_ERROR_SEND_DATA_WRITE;
1504 address += blk_len * 4;
1505 p_data += blk_len;
1506 len -= blk_len;
1507 }
1508 }
1509
1510 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1511 return HPI6000_ERROR_SEND_DATA_IDLECMD;
1512
1513 hpi6000_send_dsp_interrupt(pdo);
1514
1515 data_sent += length * 4;
1516 }
1517 if (!time_out)
1518 return HPI6000_ERROR_SEND_DATA_TIMEOUT;
1519 return 0;
1520}
1521
1522static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1523 struct hpi_message *phm, struct hpi_response *phr)
1524{
1525 struct dsp_obj *pdo =
1526 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1527 u32 data_got = 0;
1528 u16 ack;
1529 u32 length, address;
1530 u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1531
1532 (void)phr; /* this parameter not used! */
1533
1534 /* round dwDataSize down to nearest 4 bytes */
1535 while (data_got < (phm->u.d.u.data.data_size & ~3L)) {
1536 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1537 if (ack & HPI_HIF_ERROR_MASK)
1538 return HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT;
1539
1540 if (hpi6000_send_host_command(pao, dsp_index,
1541 HPI_HIF_GET_DATA))
1542 return HPI6000_ERROR_GET_DATA_CMD;
1543 hpi6000_send_dsp_interrupt(pdo);
1544
1545 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_DATA);
1546
1547 if (ack & HPI_HIF_ERROR_MASK)
1548 return HPI6000_ERROR_GET_DATA_ACK;
1549
1550 /* get the address and size */
1551 do {
1552 address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1553 length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1554 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1555
1556 /* read the data */
1557 {
1558 u32 len = length;
1559 u32 blk_len = 512;
1560 while (len) {
1561 if (len < blk_len)
1562 blk_len = len;
1563 if (hpi6000_dsp_block_read32(pao, dsp_index,
1564 address, p_data, blk_len))
1565 return HPI6000_ERROR_GET_DATA_READ;
1566 address += blk_len * 4;
1567 p_data += blk_len;
1568 len -= blk_len;
1569 }
1570 }
1571
1572 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1573 return HPI6000_ERROR_GET_DATA_IDLECMD;
1574 hpi6000_send_dsp_interrupt(pdo);
1575
1576 data_got += length * 4;
1577 }
1578 return 0;
1579}
1580
1581static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo)
1582{
1583 iowrite32(0x00030003, pdo->prHPI_control); /* DSPINT */
1584}
1585
1586static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
1587 u16 dsp_index, u32 host_cmd)
1588{
1589 struct dsp_obj *pdo =
1590 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1591 u32 timeout = TIMEOUT;
1592
1593 /* set command */
1594 do {
1595 hpi_write_word(pdo, HPI_HIF_ADDR(host_cmd), host_cmd);
1596 /* flush the FIFO */
1597 hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1598 } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) && --timeout);
1599
1600 /* reset the interrupt bit */
1601 iowrite32(0x00040004, pdo->prHPI_control);
1602
1603 if (timeout)
1604 return 0;
1605 else
1606 return 1;
1607}
1608
1609/* if the PCI2040 has recorded an HPI timeout, reset the error and return 1 */
1610static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
1611 u16 read_or_write)
1612{
1613 u32 hPI_error;
1614
1615 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
1616
1617 /* read the error bits from the PCI2040 */
1618 hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1619 if (hPI_error) {
1620 /* reset the error flag */
1621 iowrite32(0L, phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1622 phw->pCI2040HPI_error_count++;
1623 if (read_or_write == 1)
1624 gw_pci_read_asserts++; /************* inc global */
1625 else
1626 gw_pci_write_asserts++;
1627 return 1;
1628 } else
1629 return 0;
1630}
1631
1632static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
1633 u32 ack_value)
1634{
1635 struct dsp_obj *pdo =
1636 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1637 u32 ack = 0L;
1638 u32 timeout;
1639 u32 hPIC = 0L;
1640
1641 /* wait for host interrupt to signal ack is ready */
1642 timeout = TIMEOUT;
1643 while (--timeout) {
1644 hPIC = ioread32(pdo->prHPI_control);
1645 if (hPIC & 0x04) /* 0x04 = HINT from DSP */
1646 break;
1647 }
1648 if (timeout == 0)
1649 return HPI_HIF_ERROR_MASK;
1650
1651 /* wait for dwAckValue */
1652 timeout = TIMEOUT;
1653 while (--timeout) {
1654 /* read the ack mailbox */
1655 ack = hpi_read_word(pdo, HPI_HIF_ADDR(dsp_ack));
1656 if (ack == ack_value)
1657 break;
1658 if ((ack & HPI_HIF_ERROR_MASK)
1659 && !hpi6000_check_PCI2040_error_flag(pao, H6READ))
1660 break;
1661 /*for (i=0;i<1000;i++) */
1662 /* dwPause=i+1; */
1663 }
1664 if (ack & HPI_HIF_ERROR_MASK)
1665 /* indicates bad read from DSP -
1666 typically 0xffffff is read for some reason */
1667 ack = HPI_HIF_ERROR_MASK;
1668
1669 if (timeout == 0)
1670 ack = HPI_HIF_ERROR_MASK;
1671 return (short)ack;
1672}
1673
1674static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
1675 struct hpi_message *phm)
1676{
1677 const u16 dsp_index = 0;
1678 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
1679 struct dsp_obj *pdo = &phw->ado[dsp_index];
1680 u32 timeout;
1681 u32 cache_dirty_flag;
1682 u16 err;
1683
1684 hpios_dsplock_lock(pao);
1685
1686 timeout = TIMEOUT;
1687 do {
1688 cache_dirty_flag =
1689 hpi_read_word((struct dsp_obj *)pdo,
1690 HPI_HIF_ADDR(control_cache_is_dirty));
1691 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1692 if (!timeout) {
1693 err = HPI6000_ERROR_CONTROL_CACHE_PARAMS;
1694 goto unlock;
1695 }
1696
1697 if (cache_dirty_flag) {
1698 /* read the cached controls */
1699 u32 address;
1700 u32 length;
1701
1702 timeout = TIMEOUT;
1703 if (pdo->control_cache_address_on_dsp == 0) {
1704 do {
1705 address =
1706 hpi_read_word((struct dsp_obj *)pdo,
1707 HPI_HIF_ADDR(control_cache_address));
1708
1709 length = hpi_read_word((struct dsp_obj *)pdo,
1710 HPI_HIF_ADDR
1711 (control_cache_size_in_bytes));
1712 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1713 && --timeout);
1714 if (!timeout) {
1715 err = HPI6000_ERROR_CONTROL_CACHE_ADDRLEN;
1716 goto unlock;
1717 }
1718 pdo->control_cache_address_on_dsp = address;
1719 pdo->control_cache_length_on_dsp = length;
1720 } else {
1721 address = pdo->control_cache_address_on_dsp;
1722 length = pdo->control_cache_length_on_dsp;
1723 }
1724
1725 if (hpi6000_dsp_block_read32(pao, dsp_index, address,
1726 (u32 *)&phw->control_cache[0],
1727 length / sizeof(u32))) {
1728 err = HPI6000_ERROR_CONTROL_CACHE_READ;
1729 goto unlock;
1730 }
1731 do {
1732 hpi_write_word((struct dsp_obj *)pdo,
1733 HPI_HIF_ADDR(control_cache_is_dirty), 0);
1734 /* flush the FIFO */
1735 hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1736 } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1737 && --timeout);
1738 if (!timeout) {
1739 err = HPI6000_ERROR_CONTROL_CACHE_FLUSH;
1740 goto unlock;
1741 }
1742
1743 }
1744 err = 0;
1745
1746unlock:
1747 hpios_dsplock_unlock(pao);
1748 return err;
1749}
1750
1751/** Get dsp index for multi DSP adapters only */
1752static u16 get_dsp_index(struct hpi_adapter_obj *pao, struct hpi_message *phm)
1753{
1754 u16 ret = 0;
1755 switch (phm->object) {
1756 case HPI_OBJ_ISTREAM:
1757 if (phm->obj_index < 2)
1758 ret = 1;
1759 break;
1760 case HPI_OBJ_PROFILE:
1761 ret = phm->obj_index;
1762 break;
1763 default:
1764 break;
1765 }
1766 return ret;
1767}
1768
1769/** Complete transaction with DSP
1770
1771Send message, get response, send or get stream data if any.
1772*/
1773static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
1774 struct hpi_response *phr)
1775{
1776 u16 error = 0;
1777 u16 dsp_index = 0;
1778 u16 num_dsp = ((struct hpi_hw_obj *)pao->priv)->num_dsp;
1779 hpios_dsplock_lock(pao);
1780
1781 if (num_dsp < 2)
1782 dsp_index = 0;
1783 else {
1784 dsp_index = get_dsp_index(pao, phm);
1785
1786 /* is this checked on the DSP anyway? */
1787 if ((phm->function == HPI_ISTREAM_GROUP_ADD)
1788 || (phm->function == HPI_OSTREAM_GROUP_ADD)) {
1789 struct hpi_message hm;
1790 u16 add_index;
1791 hm.obj_index = phm->u.d.u.stream.stream_index;
1792 hm.object = phm->u.d.u.stream.object_type;
1793 add_index = get_dsp_index(pao, &hm);
1794 if (add_index != dsp_index) {
1795 phr->error = HPI_ERROR_NO_INTERDSP_GROUPS;
1796 return;
1797 }
1798 }
1799 }
1800 error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
1801
1802 /* maybe an error response */
1803 if (error) {
1804 /* something failed in the HPI/DSP interface */
1805 phr->error = error;
1806 /* just the header of the response is valid */
1807 phr->size = sizeof(struct hpi_response_header);
1808 goto err;
1809 }
1810
1811 if (phr->error != 0) /* something failed in the DSP */
1812 goto err;
1813
1814 switch (phm->function) {
1815 case HPI_OSTREAM_WRITE:
1816 case HPI_ISTREAM_ANC_WRITE:
1817 error = hpi6000_send_data(pao, dsp_index, phm, phr);
1818 break;
1819 case HPI_ISTREAM_READ:
1820 case HPI_OSTREAM_ANC_READ:
1821 error = hpi6000_get_data(pao, dsp_index, phm, phr);
1822 break;
1823 case HPI_ADAPTER_GET_ASSERT:
1824 phr->u.a.adapter_index = 0; /* dsp 0 default */
1825 if (num_dsp == 2) {
1826 if (!phr->u.a.adapter_type) {
1827 /* no assert from dsp 0, check dsp 1 */
1828 error = hpi6000_message_response_sequence(pao,
1829 1, phm, phr);
1830 phr->u.a.adapter_index = 1;
1831 }
1832 }
1833 }
1834
1835 if (error)
1836 phr->error = error;
1837
1838err:
1839 hpios_dsplock_unlock(pao);
1840 return;
1841}
diff --git a/sound/pci/asihpi/hpi6000.h b/sound/pci/asihpi/hpi6000.h
new file mode 100644
index 000000000000..4c7d507c0ecd
--- /dev/null
+++ b/sound/pci/asihpi/hpi6000.h
@@ -0,0 +1,70 @@
1/*****************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Public declarations for DSP Proramming Interface to TI C6701
20
21Shared between hpi6000.c and DSP code
22
23(C) Copyright AudioScience Inc. 1998-2003
24******************************************************************************/
25
26#ifndef _HPI6000_H_
27#define _HPI6000_H_
28
29#define HPI_NMIXER_CONTROLS 200
30
31/*
32 * Control caching is always supported in the HPI code.
33 * The DSP should make sure that dwControlCacheSizeInBytes is initialized to 0
34 * during boot to make it in-active.
35 */
36struct hpi_hif_6000 {
37 u32 host_cmd;
38 u32 dsp_ack;
39 u32 address;
40 u32 length;
41 u32 message_buffer_address;
42 u32 response_buffer_address;
43 u32 dsp_number;
44 u32 adapter_info;
45 u32 control_cache_is_dirty;
46 u32 control_cache_address;
47 u32 control_cache_size_in_bytes;
48 u32 control_cache_count;
49};
50
51#define HPI_HIF_PACK_ADAPTER_INFO(adapter, version_major, version_minor) \
52 ((adapter << 16) | (version_major << 8) | version_minor)
53#define HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER(adapterinfo) \
54 ((adapterinfo >> 16) & 0xffff)
55#define HPI_HIF_ADAPTER_INFO_EXTRACT_HWVERSION_MAJOR(adapterinfo) \
56 ((adapterinfo >> 8) & 0xff)
57#define HPI_HIF_ADAPTER_INFO_EXTRACT_HWVERSION_MINOR(adapterinfo) \
58 (adapterinfo & 0xff)
59
60/* Command/status exchanged between host and DSP */
61#define HPI_HIF_IDLE 0
62#define HPI_HIF_SEND_MSG 1
63#define HPI_HIF_GET_RESP 2
64#define HPI_HIF_DATA_MASK 0x10
65#define HPI_HIF_SEND_DATA 0x13
66#define HPI_HIF_GET_DATA 0x14
67#define HPI_HIF_SEND_DONE 5
68#define HPI_HIF_RESET 9
69
70#endif /* _HPI6000_H_ */
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
new file mode 100644
index 000000000000..8df2ff76d944
--- /dev/null
+++ b/sound/pci/asihpi/hpi6205.c
@@ -0,0 +1,2332 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Hardware Programming Interface (HPI) for AudioScience
20 ASI50xx, AS51xx, ASI6xxx, ASI87xx ASI89xx series adapters.
21 These PCI and PCIe bus adapters are based on a
22 TMS320C6205 PCI bus mastering DSP,
23 and (except ASI50xx) TI TMS320C6xxx floating point DSP
24
25 Exported function:
26 void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
27
28(C) Copyright AudioScience Inc. 1998-2010
29*******************************************************************************/
30#define SOURCEFILE_NAME "hpi6205.c"
31
32#include "hpi_internal.h"
33#include "hpimsginit.h"
34#include "hpidebug.h"
35#include "hpi6205.h"
36#include "hpidspcd.h"
37#include "hpicmn.h"
38
39/*****************************************************************************/
40/* HPI6205 specific error codes */
41#define HPI6205_ERROR_BASE 1000
42/*#define HPI6205_ERROR_MEM_ALLOC 1001 */
43#define HPI6205_ERROR_6205_NO_IRQ 1002
44#define HPI6205_ERROR_6205_INIT_FAILED 1003
45/*#define HPI6205_ERROR_MISSING_DSPCODE 1004 */
46#define HPI6205_ERROR_UNKNOWN_PCI_DEVICE 1005
47#define HPI6205_ERROR_6205_REG 1006
48#define HPI6205_ERROR_6205_DSPPAGE 1007
49#define HPI6205_ERROR_BAD_DSPINDEX 1008
50#define HPI6205_ERROR_C6713_HPIC 1009
51#define HPI6205_ERROR_C6713_HPIA 1010
52#define HPI6205_ERROR_C6713_PLL 1011
53#define HPI6205_ERROR_DSP_INTMEM 1012
54#define HPI6205_ERROR_DSP_EXTMEM 1013
55#define HPI6205_ERROR_DSP_PLD 1014
56#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 1015
57#define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016
58#define HPI6205_ERROR_6205_EEPROM 1017
59#define HPI6205_ERROR_DSP_EMIF 1018
60
61#define hpi6205_error(dsp_index, err) (err)
62/*****************************************************************************/
63/* for C6205 PCI i/f */
64/* Host Status Register (HSR) bitfields */
65#define C6205_HSR_INTSRC 0x01
66#define C6205_HSR_INTAVAL 0x02
67#define C6205_HSR_INTAM 0x04
68#define C6205_HSR_CFGERR 0x08
69#define C6205_HSR_EEREAD 0x10
70/* Host-to-DSP Control Register (HDCR) bitfields */
71#define C6205_HDCR_WARMRESET 0x01
72#define C6205_HDCR_DSPINT 0x02
73#define C6205_HDCR_PCIBOOT 0x04
74/* DSP Page Register (DSPP) bitfields, */
75/* defines 4 Mbyte page that BAR0 points to */
76#define C6205_DSPP_MAP1 0x400
77
78/* BAR0 maps to prefetchable 4 Mbyte memory block set by DSPP.
79 * BAR1 maps to non-prefetchable 8 Mbyte memory block
80 * of DSP memory mapped registers (starting at 0x01800000).
81 * 0x01800000 is hardcoded in the PCI i/f, so that only the offset from this
82 * needs to be added to the BAR1 base address set in the PCI config reg
83 */
84#define C6205_BAR1_PCI_IO_OFFSET (0x027FFF0L)
85#define C6205_BAR1_HSR (C6205_BAR1_PCI_IO_OFFSET)
86#define C6205_BAR1_HDCR (C6205_BAR1_PCI_IO_OFFSET+4)
87#define C6205_BAR1_DSPP (C6205_BAR1_PCI_IO_OFFSET+8)
88
89/* used to control LED (revA) and reset C6713 (revB) */
90#define C6205_BAR0_TIMER1_CTL (0x01980000L)
91
92/* For first 6713 in CE1 space, using DA17,16,2 */
93#define HPICL_ADDR 0x01400000L
94#define HPICH_ADDR 0x01400004L
95#define HPIAL_ADDR 0x01410000L
96#define HPIAH_ADDR 0x01410004L
97#define HPIDIL_ADDR 0x01420000L
98#define HPIDIH_ADDR 0x01420004L
99#define HPIDL_ADDR 0x01430000L
100#define HPIDH_ADDR 0x01430004L
101
102#define C6713_EMIF_GCTL 0x01800000
103#define C6713_EMIF_CE1 0x01800004
104#define C6713_EMIF_CE0 0x01800008
105#define C6713_EMIF_CE2 0x01800010
106#define C6713_EMIF_CE3 0x01800014
107#define C6713_EMIF_SDRAMCTL 0x01800018
108#define C6713_EMIF_SDRAMTIMING 0x0180001C
109#define C6713_EMIF_SDRAMEXT 0x01800020
110
111struct hpi_hw_obj {
112 /* PCI registers */
113 __iomem u32 *prHSR;
114 __iomem u32 *prHDCR;
115 __iomem u32 *prDSPP;
116
117 u32 dsp_page;
118
119 struct consistent_dma_area h_locked_mem;
120 struct bus_master_interface *p_interface_buffer;
121
122 u16 flag_outstream_just_reset[HPI_MAX_STREAMS];
123 /* a non-NULL handle means there is an HPI allocated buffer */
124 struct consistent_dma_area instream_host_buffers[HPI_MAX_STREAMS];
125 struct consistent_dma_area outstream_host_buffers[HPI_MAX_STREAMS];
126 /* non-zero size means a buffer exists, may be external */
127 u32 instream_host_buffer_size[HPI_MAX_STREAMS];
128 u32 outstream_host_buffer_size[HPI_MAX_STREAMS];
129
130 struct consistent_dma_area h_control_cache;
131 struct consistent_dma_area h_async_event_buffer;
132/* struct hpi_control_cache_single *pControlCache; */
133 struct hpi_async_event *p_async_event_buffer;
134 struct hpi_control_cache *p_cache;
135};
136
137/*****************************************************************************/
138/* local prototypes */
139
140#define check_before_bbm_copy(status, p_bbm_data, l_first_write, l_second_write)
141
142static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us);
143
144static void send_dsp_command(struct hpi_hw_obj *phw, int cmd);
145
146static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
147 u32 *pos_error_code);
148
149static u16 message_response_sequence(struct hpi_adapter_obj *pao,
150 struct hpi_message *phm, struct hpi_response *phr);
151
152static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
153 struct hpi_response *phr);
154
155#define HPI6205_TIMEOUT 1000000
156
157static void subsys_create_adapter(struct hpi_message *phm,
158 struct hpi_response *phr);
159static void subsys_delete_adapter(struct hpi_message *phm,
160 struct hpi_response *phr);
161
162static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
163 u32 *pos_error_code);
164
165static void delete_adapter_obj(struct hpi_adapter_obj *pao);
166
167static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
168 struct hpi_message *phm, struct hpi_response *phr);
169
170static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
171 struct hpi_message *phm, struct hpi_response *phr);
172
173static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
174 struct hpi_message *phm, struct hpi_response *phr);
175static void outstream_write(struct hpi_adapter_obj *pao,
176 struct hpi_message *phm, struct hpi_response *phr);
177
178static void outstream_get_info(struct hpi_adapter_obj *pao,
179 struct hpi_message *phm, struct hpi_response *phr);
180
181static void outstream_start(struct hpi_adapter_obj *pao,
182 struct hpi_message *phm, struct hpi_response *phr);
183
184static void outstream_open(struct hpi_adapter_obj *pao,
185 struct hpi_message *phm, struct hpi_response *phr);
186
187static void outstream_reset(struct hpi_adapter_obj *pao,
188 struct hpi_message *phm, struct hpi_response *phr);
189
190static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
191 struct hpi_message *phm, struct hpi_response *phr);
192
193static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
194 struct hpi_message *phm, struct hpi_response *phr);
195
196static void instream_host_buffer_free(struct hpi_adapter_obj *pao,
197 struct hpi_message *phm, struct hpi_response *phr);
198
199static void instream_read(struct hpi_adapter_obj *pao,
200 struct hpi_message *phm, struct hpi_response *phr);
201
202static void instream_get_info(struct hpi_adapter_obj *pao,
203 struct hpi_message *phm, struct hpi_response *phr);
204
205static void instream_start(struct hpi_adapter_obj *pao,
206 struct hpi_message *phm, struct hpi_response *phr);
207
208static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
209 u32 address);
210
211static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index,
212 u32 address, u32 data);
213
214static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao,
215 int dsp_index);
216
217static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
218 u32 address, u32 length);
219
220static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
221 int dsp_index);
222
223static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
224 int dsp_index);
225
226static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
227
228/*****************************************************************************/
229
230static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
231{
232
233 switch (phm->function) {
234 case HPI_SUBSYS_OPEN:
235 case HPI_SUBSYS_CLOSE:
236 case HPI_SUBSYS_GET_INFO:
237 case HPI_SUBSYS_DRIVER_UNLOAD:
238 case HPI_SUBSYS_DRIVER_LOAD:
239 case HPI_SUBSYS_FIND_ADAPTERS:
240 /* messages that should not get here */
241 phr->error = HPI_ERROR_UNIMPLEMENTED;
242 break;
243 case HPI_SUBSYS_CREATE_ADAPTER:
244 subsys_create_adapter(phm, phr);
245 break;
246 case HPI_SUBSYS_DELETE_ADAPTER:
247 subsys_delete_adapter(phm, phr);
248 break;
249 default:
250 phr->error = HPI_ERROR_INVALID_FUNC;
251 break;
252 }
253}
254
255static void control_message(struct hpi_adapter_obj *pao,
256 struct hpi_message *phm, struct hpi_response *phr)
257{
258
259 struct hpi_hw_obj *phw = pao->priv;
260
261 switch (phm->function) {
262 case HPI_CONTROL_GET_STATE:
263 if (pao->has_control_cache) {
264 rmb(); /* make sure we see updates DM_aed from DSP */
265 if (hpi_check_control_cache(phw->p_cache, phm, phr))
266 break;
267 }
268 hw_message(pao, phm, phr);
269 break;
270 case HPI_CONTROL_GET_INFO:
271 hw_message(pao, phm, phr);
272 break;
273 case HPI_CONTROL_SET_STATE:
274 hw_message(pao, phm, phr);
275 if (pao->has_control_cache)
276 hpi_sync_control_cache(phw->p_cache, phm, phr);
277 break;
278 default:
279 phr->error = HPI_ERROR_INVALID_FUNC;
280 break;
281 }
282}
283
284static void adapter_message(struct hpi_adapter_obj *pao,
285 struct hpi_message *phm, struct hpi_response *phr)
286{
287 switch (phm->function) {
288 default:
289 hw_message(pao, phm, phr);
290 break;
291 }
292}
293
294static void outstream_message(struct hpi_adapter_obj *pao,
295 struct hpi_message *phm, struct hpi_response *phr)
296{
297
298 if (phm->obj_index >= HPI_MAX_STREAMS) {
299 phr->error = HPI_ERROR_INVALID_STREAM;
300 HPI_DEBUG_LOG(WARNING,
301 "message referencing invalid stream %d "
302 "on adapter index %d\n", phm->obj_index,
303 phm->adapter_index);
304 return;
305 }
306
307 switch (phm->function) {
308 case HPI_OSTREAM_WRITE:
309 outstream_write(pao, phm, phr);
310 break;
311 case HPI_OSTREAM_GET_INFO:
312 outstream_get_info(pao, phm, phr);
313 break;
314 case HPI_OSTREAM_HOSTBUFFER_ALLOC:
315 outstream_host_buffer_allocate(pao, phm, phr);
316 break;
317 case HPI_OSTREAM_HOSTBUFFER_GET_INFO:
318 outstream_host_buffer_get_info(pao, phm, phr);
319 break;
320 case HPI_OSTREAM_HOSTBUFFER_FREE:
321 outstream_host_buffer_free(pao, phm, phr);
322 break;
323 case HPI_OSTREAM_START:
324 outstream_start(pao, phm, phr);
325 break;
326 case HPI_OSTREAM_OPEN:
327 outstream_open(pao, phm, phr);
328 break;
329 case HPI_OSTREAM_RESET:
330 outstream_reset(pao, phm, phr);
331 break;
332 default:
333 hw_message(pao, phm, phr);
334 break;
335 }
336}
337
338static void instream_message(struct hpi_adapter_obj *pao,
339 struct hpi_message *phm, struct hpi_response *phr)
340{
341
342 if (phm->obj_index >= HPI_MAX_STREAMS) {
343 phr->error = HPI_ERROR_INVALID_STREAM;
344 HPI_DEBUG_LOG(WARNING,
345 "message referencing invalid stream %d "
346 "on adapter index %d\n", phm->obj_index,
347 phm->adapter_index);
348 return;
349 }
350
351 switch (phm->function) {
352 case HPI_ISTREAM_READ:
353 instream_read(pao, phm, phr);
354 break;
355 case HPI_ISTREAM_GET_INFO:
356 instream_get_info(pao, phm, phr);
357 break;
358 case HPI_ISTREAM_HOSTBUFFER_ALLOC:
359 instream_host_buffer_allocate(pao, phm, phr);
360 break;
361 case HPI_ISTREAM_HOSTBUFFER_GET_INFO:
362 instream_host_buffer_get_info(pao, phm, phr);
363 break;
364 case HPI_ISTREAM_HOSTBUFFER_FREE:
365 instream_host_buffer_free(pao, phm, phr);
366 break;
367 case HPI_ISTREAM_START:
368 instream_start(pao, phm, phr);
369 break;
370 default:
371 hw_message(pao, phm, phr);
372 break;
373 }
374}
375
376/*****************************************************************************/
377/** Entry point to this HPI backend
378 * All calls to the HPI start here
379 */
380void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
381{
382 struct hpi_adapter_obj *pao = NULL;
383
384 /* subsytem messages are processed by every HPI.
385 * All other messages are ignored unless the adapter index matches
386 * an adapter in the HPI
387 */
388 HPI_DEBUG_LOG(DEBUG, "HPI obj=%d, func=%d\n", phm->object,
389 phm->function);
390
391 /* if Dsp has crashed then do not communicate with it any more */
392 if (phm->object != HPI_OBJ_SUBSYSTEM) {
393 pao = hpi_find_adapter(phm->adapter_index);
394 if (!pao) {
395 HPI_DEBUG_LOG(DEBUG,
396 " %d,%d refused, for another HPI?\n",
397 phm->object, phm->function);
398 return;
399 }
400
401 if ((pao->dsp_crashed >= 10)
402 && (phm->function != HPI_ADAPTER_DEBUG_READ)) {
403 /* allow last resort debug read even after crash */
404 hpi_init_response(phr, phm->object, phm->function,
405 HPI_ERROR_DSP_HARDWARE);
406 HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n",
407 phm->object, phm->function);
408 return;
409 }
410 }
411
412 /* Init default response */
413 if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
414 hpi_init_response(phr, phm->object, phm->function,
415 HPI_ERROR_PROCESSING_MESSAGE);
416
417 HPI_DEBUG_LOG(VERBOSE, "start of switch\n");
418 switch (phm->type) {
419 case HPI_TYPE_MESSAGE:
420 switch (phm->object) {
421 case HPI_OBJ_SUBSYSTEM:
422 subsys_message(phm, phr);
423 break;
424
425 case HPI_OBJ_ADAPTER:
426 phr->size =
427 sizeof(struct hpi_response_header) +
428 sizeof(struct hpi_adapter_res);
429 adapter_message(pao, phm, phr);
430 break;
431
432 case HPI_OBJ_CONTROLEX:
433 case HPI_OBJ_CONTROL:
434 control_message(pao, phm, phr);
435 break;
436
437 case HPI_OBJ_OSTREAM:
438 outstream_message(pao, phm, phr);
439 break;
440
441 case HPI_OBJ_ISTREAM:
442 instream_message(pao, phm, phr);
443 break;
444
445 default:
446 hw_message(pao, phm, phr);
447 break;
448 }
449 break;
450
451 default:
452 phr->error = HPI_ERROR_INVALID_TYPE;
453 break;
454 }
455}
456
457/*****************************************************************************/
458/* SUBSYSTEM */
459
460/** Create an adapter object and initialise it based on resource information
461 * passed in in the message
462 * *** NOTE - you cannot use this function AND the FindAdapters function at the
463 * same time, the application must use only one of them to get the adapters ***
464 */
465static void subsys_create_adapter(struct hpi_message *phm,
466 struct hpi_response *phr)
467{
468 /* create temp adapter obj, because we don't know what index yet */
469 struct hpi_adapter_obj ao;
470 u32 os_error_code;
471 u16 err;
472
473 HPI_DEBUG_LOG(DEBUG, " subsys_create_adapter\n");
474
475 memset(&ao, 0, sizeof(ao));
476
477 /* this HPI only creates adapters for TI/PCI devices */
478 if (phm->u.s.resource.bus_type != HPI_BUS_PCI)
479 return;
480 if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI)
481 return;
482 if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_DSP6205)
483 return;
484
485 ao.priv = kmalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
486 if (!ao.priv) {
487 HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
488 phr->error = HPI_ERROR_MEMORY_ALLOC;
489 return;
490 }
491 memset(ao.priv, 0, sizeof(struct hpi_hw_obj));
492
493 ao.pci = *phm->u.s.resource.r.pci;
494 err = create_adapter_obj(&ao, &os_error_code);
495 if (!err)
496 err = hpi_add_adapter(&ao);
497 if (err) {
498 phr->u.s.data = os_error_code;
499 delete_adapter_obj(&ao);
500 phr->error = err;
501 return;
502 }
503
504 phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
505 phr->u.s.adapter_index = ao.index;
506 phr->u.s.num_adapters++;
507 phr->error = 0;
508}
509
510/** delete an adapter - required by WDM driver */
511static void subsys_delete_adapter(struct hpi_message *phm,
512 struct hpi_response *phr)
513{
514 struct hpi_adapter_obj *pao;
515 struct hpi_hw_obj *phw;
516
517 pao = hpi_find_adapter(phm->adapter_index);
518 if (!pao) {
519 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
520 return;
521 }
522 phw = (struct hpi_hw_obj *)pao->priv;
523 /* reset adapter h/w */
524 /* Reset C6713 #1 */
525 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
526 /* reset C6205 */
527 iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);
528
529 delete_adapter_obj(pao);
530 phr->error = 0;
531}
532
533/** Create adapter object
534 allocate buffers, bootload DSPs, initialise control cache
535*/
536static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
537 u32 *pos_error_code)
538{
539 struct hpi_hw_obj *phw = pao->priv;
540 struct bus_master_interface *interface;
541 u32 phys_addr;
542#ifndef HPI6205_NO_HSR_POLL
543 u32 time_out = HPI6205_TIMEOUT;
544 u32 temp1;
545#endif
546 int i;
547 u16 err;
548
549 /* init error reporting */
550 pao->dsp_crashed = 0;
551
552 for (i = 0; i < HPI_MAX_STREAMS; i++)
553 phw->flag_outstream_just_reset[i] = 1;
554
555 /* The C6205 memory area 1 is 8Mbyte window into DSP registers */
556 phw->prHSR =
557 pao->pci.ap_mem_base[1] +
558 C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]);
559 phw->prHDCR =
560 pao->pci.ap_mem_base[1] +
561 C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]);
562 phw->prDSPP =
563 pao->pci.ap_mem_base[1] +
564 C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]);
565
566 pao->has_control_cache = 0;
567
568 if (hpios_locked_mem_alloc(&phw->h_locked_mem,
569 sizeof(struct bus_master_interface),
570 pao->pci.p_os_data))
571 phw->p_interface_buffer = NULL;
572 else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,
573 (void *)&phw->p_interface_buffer))
574 phw->p_interface_buffer = NULL;
575
576 HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n",
577 phw->p_interface_buffer);
578
579 if (phw->p_interface_buffer) {
580 memset((void *)phw->p_interface_buffer, 0,
581 sizeof(struct bus_master_interface));
582 phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN;
583 }
584
585 err = adapter_boot_load_dsp(pao, pos_error_code);
586 if (err)
587 /* no need to clean up as SubSysCreateAdapter */
588 /* calls DeleteAdapter on error. */
589 return err;
590
591 HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
592
593 /* allow boot load even if mem alloc wont work */
594 if (!phw->p_interface_buffer)
595 return hpi6205_error(0, HPI_ERROR_MEMORY_ALLOC);
596
597 interface = phw->p_interface_buffer;
598
599#ifndef HPI6205_NO_HSR_POLL
600 /* wait for first interrupt indicating the DSP init is done */
601 time_out = HPI6205_TIMEOUT * 10;
602 temp1 = 0;
603 while (((temp1 & C6205_HSR_INTSRC) == 0) && --time_out)
604 temp1 = ioread32(phw->prHSR);
605
606 if (temp1 & C6205_HSR_INTSRC)
607 HPI_DEBUG_LOG(INFO,
608 "interrupt confirming DSP code running OK\n");
609 else {
610 HPI_DEBUG_LOG(ERROR,
611 "timed out waiting for interrupt "
612 "confirming DSP code running\n");
613 return hpi6205_error(0, HPI6205_ERROR_6205_NO_IRQ);
614 }
615
616 /* reset the interrupt */
617 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
618#endif
619
620 /* make sure the DSP has started ok */
621 if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {
622 HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");
623 return hpi6205_error(0, HPI6205_ERROR_6205_INIT_FAILED);
624 }
625 /* Note that *pao, *phw are zeroed after allocation,
626 * so pointers and flags are NULL by default.
627 * Allocate bus mastering control cache buffer and tell the DSP about it
628 */
629 if (interface->control_cache.number_of_controls) {
630 void *p_control_cache_virtual;
631
632 err = hpios_locked_mem_alloc(&phw->h_control_cache,
633 interface->control_cache.size_in_bytes,
634 pao->pci.p_os_data);
635 if (!err)
636 err = hpios_locked_mem_get_virt_addr(&phw->
637 h_control_cache, &p_control_cache_virtual);
638 if (!err) {
639 memset(p_control_cache_virtual, 0,
640 interface->control_cache.size_in_bytes);
641
642 phw->p_cache =
643 hpi_alloc_control_cache(interface->
644 control_cache.number_of_controls,
645 interface->control_cache.size_in_bytes,
646 (struct hpi_control_cache_info *)
647 p_control_cache_virtual);
648 }
649 if (!err) {
650 err = hpios_locked_mem_get_phys_addr(&phw->
651 h_control_cache, &phys_addr);
652 interface->control_cache.physical_address32 =
653 phys_addr;
654 }
655
656 if (!err)
657 pao->has_control_cache = 1;
658 else {
659 if (hpios_locked_mem_valid(&phw->h_control_cache))
660 hpios_locked_mem_free(&phw->h_control_cache);
661 pao->has_control_cache = 0;
662 }
663 }
664 /* allocate bus mastering async buffer and tell the DSP about it */
665 if (interface->async_buffer.b.size) {
666 err = hpios_locked_mem_alloc(&phw->h_async_event_buffer,
667 interface->async_buffer.b.size *
668 sizeof(struct hpi_async_event), pao->pci.p_os_data);
669 if (!err)
670 err = hpios_locked_mem_get_virt_addr
671 (&phw->h_async_event_buffer, (void *)
672 &phw->p_async_event_buffer);
673 if (!err)
674 memset((void *)phw->p_async_event_buffer, 0,
675 interface->async_buffer.b.size *
676 sizeof(struct hpi_async_event));
677 if (!err) {
678 err = hpios_locked_mem_get_phys_addr
679 (&phw->h_async_event_buffer, &phys_addr);
680 interface->async_buffer.physical_address32 =
681 phys_addr;
682 }
683 if (err) {
684 if (hpios_locked_mem_valid(&phw->
685 h_async_event_buffer)) {
686 hpios_locked_mem_free
687 (&phw->h_async_event_buffer);
688 phw->p_async_event_buffer = NULL;
689 }
690 }
691 }
692 send_dsp_command(phw, H620_HIF_IDLE);
693
694 {
695 struct hpi_message hM;
696 struct hpi_response hR;
697 u32 max_streams;
698
699 HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
700 memset(&hM, 0, sizeof(hM));
701 hM.type = HPI_TYPE_MESSAGE;
702 hM.size = sizeof(hM);
703 hM.object = HPI_OBJ_ADAPTER;
704 hM.function = HPI_ADAPTER_GET_INFO;
705 hM.adapter_index = 0;
706 memset(&hR, 0, sizeof(hR));
707 hR.size = sizeof(hR);
708
709 err = message_response_sequence(pao, &hM, &hR);
710 if (err) {
711 HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
712 err);
713 return err;
714 }
715 if (hR.error)
716 return hR.error;
717
718 pao->adapter_type = hR.u.a.adapter_type;
719 pao->index = hR.u.a.adapter_index;
720
721 max_streams = hR.u.a.num_outstreams + hR.u.a.num_instreams;
722
723 hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams,
724 65536, pao->pci.p_os_data);
725
726 HPI_DEBUG_LOG(VERBOSE,
727 "got adapter info type %x index %d serial %d\n",
728 hR.u.a.adapter_type, hR.u.a.adapter_index,
729 hR.u.a.serial_number);
730 }
731
732 pao->open = 0; /* upon creation the adapter is closed */
733
734 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
735 return 0;
736}
737
738/** Free memory areas allocated by adapter
739 * this routine is called from SubSysDeleteAdapter,
740 * and SubSysCreateAdapter if duplicate index
741*/
742static void delete_adapter_obj(struct hpi_adapter_obj *pao)
743{
744 struct hpi_hw_obj *phw;
745 int i;
746
747 phw = pao->priv;
748
749 if (hpios_locked_mem_valid(&phw->h_async_event_buffer)) {
750 hpios_locked_mem_free(&phw->h_async_event_buffer);
751 phw->p_async_event_buffer = NULL;
752 }
753
754 if (hpios_locked_mem_valid(&phw->h_control_cache)) {
755 hpios_locked_mem_free(&phw->h_control_cache);
756 hpi_free_control_cache(phw->p_cache);
757 }
758
759 if (hpios_locked_mem_valid(&phw->h_locked_mem)) {
760 hpios_locked_mem_free(&phw->h_locked_mem);
761 phw->p_interface_buffer = NULL;
762 }
763
764 for (i = 0; i < HPI_MAX_STREAMS; i++)
765 if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) {
766 hpios_locked_mem_free(&phw->instream_host_buffers[i]);
767 /*?phw->InStreamHostBuffers[i] = NULL; */
768 phw->instream_host_buffer_size[i] = 0;
769 }
770
771 for (i = 0; i < HPI_MAX_STREAMS; i++)
772 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) {
773 hpios_locked_mem_free(&phw->outstream_host_buffers
774 [i]);
775 phw->outstream_host_buffer_size[i] = 0;
776 }
777
778 hpios_locked_mem_unprepare(pao->pci.p_os_data);
779
780 hpi_delete_adapter(pao);
781 kfree(phw);
782}
783
784/*****************************************************************************/
785/* OutStream Host buffer functions */
786
787/** Allocate or attach buffer for busmastering
788*/
789static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
790 struct hpi_message *phm, struct hpi_response *phr)
791{
792 u16 err = 0;
793 u32 command = phm->u.d.u.buffer.command;
794 struct hpi_hw_obj *phw = pao->priv;
795 struct bus_master_interface *interface = phw->p_interface_buffer;
796
797 hpi_init_response(phr, phm->object, phm->function, 0);
798
799 if (command == HPI_BUFFER_CMD_EXTERNAL
800 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
801 /* ALLOC phase, allocate a buffer with power of 2 size,
802 get its bus address for PCI bus mastering
803 */
804 phm->u.d.u.buffer.buffer_size =
805 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
806 /* return old size and allocated size,
807 so caller can detect change */
808 phr->u.d.u.stream_info.data_available =
809 phw->outstream_host_buffer_size[phm->obj_index];
810 phr->u.d.u.stream_info.buffer_size =
811 phm->u.d.u.buffer.buffer_size;
812
813 if (phw->outstream_host_buffer_size[phm->obj_index] ==
814 phm->u.d.u.buffer.buffer_size) {
815 /* Same size, no action required */
816 return;
817 }
818
819 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
820 obj_index]))
821 hpios_locked_mem_free(&phw->outstream_host_buffers
822 [phm->obj_index]);
823
824 err = hpios_locked_mem_alloc(&phw->outstream_host_buffers
825 [phm->obj_index], phm->u.d.u.buffer.buffer_size,
826 pao->pci.p_os_data);
827
828 if (err) {
829 phr->error = HPI_ERROR_INVALID_DATASIZE;
830 phw->outstream_host_buffer_size[phm->obj_index] = 0;
831 return;
832 }
833
834 err = hpios_locked_mem_get_phys_addr
835 (&phw->outstream_host_buffers[phm->obj_index],
836 &phm->u.d.u.buffer.pci_address);
837 /* get the phys addr into msg for single call alloc caller
838 * needs to do this for split alloc (or use the same message)
839 * return the phy address for split alloc in the respose too
840 */
841 phr->u.d.u.stream_info.auxiliary_data_available =
842 phm->u.d.u.buffer.pci_address;
843
844 if (err) {
845 hpios_locked_mem_free(&phw->outstream_host_buffers
846 [phm->obj_index]);
847 phw->outstream_host_buffer_size[phm->obj_index] = 0;
848 phr->error = HPI_ERROR_MEMORY_ALLOC;
849 return;
850 }
851 }
852
853 if (command == HPI_BUFFER_CMD_EXTERNAL
854 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
855 /* GRANT phase. Set up the BBM status, tell the DSP about
856 the buffer so it can start using BBM.
857 */
858 struct hpi_hostbuffer_status *status;
859
860 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
861 buffer_size - 1)) {
862 HPI_DEBUG_LOG(ERROR,
863 "buffer size must be 2^N not %d\n",
864 phm->u.d.u.buffer.buffer_size);
865 phr->error = HPI_ERROR_INVALID_DATASIZE;
866 return;
867 }
868 phw->outstream_host_buffer_size[phm->obj_index] =
869 phm->u.d.u.buffer.buffer_size;
870 status = &interface->outstream_host_buffer_status[phm->
871 obj_index];
872 status->samples_processed = 0;
873 status->stream_state = HPI_STATE_STOPPED;
874 status->dSP_index = 0;
875 status->host_index = status->dSP_index;
876 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
877
878 hw_message(pao, phm, phr);
879
880 if (phr->error
881 && hpios_locked_mem_valid(&phw->
882 outstream_host_buffers[phm->obj_index])) {
883 hpios_locked_mem_free(&phw->outstream_host_buffers
884 [phm->obj_index]);
885 phw->outstream_host_buffer_size[phm->obj_index] = 0;
886 }
887 }
888}
889
890static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
891 struct hpi_message *phm, struct hpi_response *phr)
892{
893 struct hpi_hw_obj *phw = pao->priv;
894 struct bus_master_interface *interface = phw->p_interface_buffer;
895 struct hpi_hostbuffer_status *status;
896 u8 *p_bbm_data;
897
898 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
899 obj_index])) {
900 if (hpios_locked_mem_get_virt_addr(&phw->
901 outstream_host_buffers[phm->obj_index],
902 (void *)&p_bbm_data)) {
903 phr->error = HPI_ERROR_INVALID_OPERATION;
904 return;
905 }
906 status = &interface->outstream_host_buffer_status[phm->
907 obj_index];
908 hpi_init_response(phr, HPI_OBJ_OSTREAM,
909 HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0);
910 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
911 phr->u.d.u.hostbuffer_info.p_status = status;
912 } else {
913 hpi_init_response(phr, HPI_OBJ_OSTREAM,
914 HPI_OSTREAM_HOSTBUFFER_GET_INFO,
915 HPI_ERROR_INVALID_OPERATION);
916 }
917}
918
919static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
920 struct hpi_message *phm, struct hpi_response *phr)
921{
922 struct hpi_hw_obj *phw = pao->priv;
923 u32 command = phm->u.d.u.buffer.command;
924
925 if (phw->outstream_host_buffer_size[phm->obj_index]) {
926 if (command == HPI_BUFFER_CMD_EXTERNAL
927 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
928 phw->outstream_host_buffer_size[phm->obj_index] = 0;
929 hw_message(pao, phm, phr);
930 /* Tell adapter to stop using the host buffer. */
931 }
932 if (command == HPI_BUFFER_CMD_EXTERNAL
933 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
934 hpios_locked_mem_free(&phw->outstream_host_buffers
935 [phm->obj_index]);
936 }
937 /* Should HPI_ERROR_INVALID_OPERATION be returned
938 if no host buffer is allocated? */
939 else
940 hpi_init_response(phr, HPI_OBJ_OSTREAM,
941 HPI_OSTREAM_HOSTBUFFER_FREE, 0);
942
943}
944
945static long outstream_get_space_available(struct hpi_hostbuffer_status
946 *status)
947{
948 return status->size_in_bytes - ((long)(status->host_index) -
949 (long)(status->dSP_index));
950}
951
952static void outstream_write(struct hpi_adapter_obj *pao,
953 struct hpi_message *phm, struct hpi_response *phr)
954{
955 struct hpi_hw_obj *phw = pao->priv;
956 struct bus_master_interface *interface = phw->p_interface_buffer;
957 struct hpi_hostbuffer_status *status;
958 long space_available;
959
960 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
961 /* there is no BBM buffer, write via message */
962 hw_message(pao, phm, phr);
963 return;
964 }
965
966 hpi_init_response(phr, phm->object, phm->function, 0);
967 status = &interface->outstream_host_buffer_status[phm->obj_index];
968
969 if (phw->flag_outstream_just_reset[phm->obj_index]) {
970 /* Format can only change after reset. Must tell DSP. */
971 u16 function = phm->function;
972 phw->flag_outstream_just_reset[phm->obj_index] = 0;
973 phm->function = HPI_OSTREAM_SET_FORMAT;
974 hw_message(pao, phm, phr); /* send the format to the DSP */
975 phm->function = function;
976 if (phr->error)
977 return;
978 }
979#if 1
980 if (phw->flag_outstream_just_reset[phm->obj_index]) {
981 /* First OutStremWrite() call following reset will write data to the
982 adapter's buffers, reducing delay before stream can start
983 */
984 int partial_write = 0;
985 unsigned int original_size = 0;
986
987 /* Send the first buffer to the DSP the old way. */
988 /* Limit size of first transfer - */
989 /* expect that this will not usually be triggered. */
990 if (phm->u.d.u.data.data_size > HPI6205_SIZEOF_DATA) {
991 partial_write = 1;
992 original_size = phm->u.d.u.data.data_size;
993 phm->u.d.u.data.data_size = HPI6205_SIZEOF_DATA;
994 }
995 /* write it */
996 phm->function = HPI_OSTREAM_WRITE;
997 hw_message(pao, phm, phr);
998 /* update status information that the DSP would typically
999 * update (and will update next time the DSP
1000 * buffer update task reads data from the host BBM buffer)
1001 */
1002 status->auxiliary_data_available = phm->u.d.u.data.data_size;
1003 status->host_index += phm->u.d.u.data.data_size;
1004 status->dSP_index += phm->u.d.u.data.data_size;
1005
1006 /* if we did a full write, we can return from here. */
1007 if (!partial_write)
1008 return;
1009
1010 /* tweak buffer parameters and let the rest of the */
1011 /* buffer land in internal BBM buffer */
1012 phm->u.d.u.data.data_size =
1013 original_size - HPI6205_SIZEOF_DATA;
1014 phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA;
1015 }
1016#endif
1017
1018 space_available = outstream_get_space_available(status);
1019 if (space_available < (long)phm->u.d.u.data.data_size) {
1020 phr->error = HPI_ERROR_INVALID_DATASIZE;
1021 return;
1022 }
1023
1024 /* HostBuffers is used to indicate host buffer is internally allocated.
1025 otherwise, assumed external, data written externally */
1026 if (phm->u.d.u.data.pb_data
1027 && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
1028 obj_index])) {
1029 u8 *p_bbm_data;
1030 long l_first_write;
1031 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
1032
1033 if (hpios_locked_mem_get_virt_addr(&phw->
1034 outstream_host_buffers[phm->obj_index],
1035 (void *)&p_bbm_data)) {
1036 phr->error = HPI_ERROR_INVALID_OPERATION;
1037 return;
1038 }
1039
1040 /* either all data,
1041 or enough to fit from current to end of BBM buffer */
1042 l_first_write =
1043 min(phm->u.d.u.data.data_size,
1044 status->size_in_bytes -
1045 (status->host_index & (status->size_in_bytes - 1)));
1046
1047 memcpy(p_bbm_data +
1048 (status->host_index & (status->size_in_bytes - 1)),
1049 p_app_data, l_first_write);
1050 /* remaining data if any */
1051 memcpy(p_bbm_data, p_app_data + l_first_write,
1052 phm->u.d.u.data.data_size - l_first_write);
1053 }
1054 status->host_index += phm->u.d.u.data.data_size;
1055}
1056
1057static void outstream_get_info(struct hpi_adapter_obj *pao,
1058 struct hpi_message *phm, struct hpi_response *phr)
1059{
1060 struct hpi_hw_obj *phw = pao->priv;
1061 struct bus_master_interface *interface = phw->p_interface_buffer;
1062 struct hpi_hostbuffer_status *status;
1063
1064 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
1065 hw_message(pao, phm, phr);
1066 return;
1067 }
1068
1069 hpi_init_response(phr, phm->object, phm->function, 0);
1070
1071 status = &interface->outstream_host_buffer_status[phm->obj_index];
1072
1073 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1074 phr->u.d.u.stream_info.samples_transferred =
1075 status->samples_processed;
1076 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1077 phr->u.d.u.stream_info.data_available =
1078 status->size_in_bytes - outstream_get_space_available(status);
1079 phr->u.d.u.stream_info.auxiliary_data_available =
1080 status->auxiliary_data_available;
1081}
1082
1083static void outstream_start(struct hpi_adapter_obj *pao,
1084 struct hpi_message *phm, struct hpi_response *phr)
1085{
1086 hw_message(pao, phm, phr);
1087}
1088
1089static void outstream_reset(struct hpi_adapter_obj *pao,
1090 struct hpi_message *phm, struct hpi_response *phr)
1091{
1092 struct hpi_hw_obj *phw = pao->priv;
1093 phw->flag_outstream_just_reset[phm->obj_index] = 1;
1094 hw_message(pao, phm, phr);
1095}
1096
1097static void outstream_open(struct hpi_adapter_obj *pao,
1098 struct hpi_message *phm, struct hpi_response *phr)
1099{
1100 outstream_reset(pao, phm, phr);
1101}
1102
1103/*****************************************************************************/
1104/* InStream Host buffer functions */
1105
1106static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
1107 struct hpi_message *phm, struct hpi_response *phr)
1108{
1109 u16 err = 0;
1110 u32 command = phm->u.d.u.buffer.command;
1111 struct hpi_hw_obj *phw = pao->priv;
1112 struct bus_master_interface *interface = phw->p_interface_buffer;
1113
1114 hpi_init_response(phr, phm->object, phm->function, 0);
1115
1116 if (command == HPI_BUFFER_CMD_EXTERNAL
1117 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
1118
1119 phm->u.d.u.buffer.buffer_size =
1120 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
1121 phr->u.d.u.stream_info.data_available =
1122 phw->instream_host_buffer_size[phm->obj_index];
1123 phr->u.d.u.stream_info.buffer_size =
1124 phm->u.d.u.buffer.buffer_size;
1125
1126 if (phw->instream_host_buffer_size[phm->obj_index] ==
1127 phm->u.d.u.buffer.buffer_size) {
1128 /* Same size, no action required */
1129 return;
1130 }
1131
1132 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1133 obj_index]))
1134 hpios_locked_mem_free(&phw->instream_host_buffers
1135 [phm->obj_index]);
1136
1137 err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->
1138 obj_index], phm->u.d.u.buffer.buffer_size,
1139 pao->pci.p_os_data);
1140
1141 if (err) {
1142 phr->error = HPI_ERROR_INVALID_DATASIZE;
1143 phw->instream_host_buffer_size[phm->obj_index] = 0;
1144 return;
1145 }
1146
1147 err = hpios_locked_mem_get_phys_addr
1148 (&phw->instream_host_buffers[phm->obj_index],
1149 &phm->u.d.u.buffer.pci_address);
1150 /* get the phys addr into msg for single call alloc. Caller
1151 needs to do this for split alloc so return the phy address */
1152 phr->u.d.u.stream_info.auxiliary_data_available =
1153 phm->u.d.u.buffer.pci_address;
1154 if (err) {
1155 hpios_locked_mem_free(&phw->instream_host_buffers
1156 [phm->obj_index]);
1157 phw->instream_host_buffer_size[phm->obj_index] = 0;
1158 phr->error = HPI_ERROR_MEMORY_ALLOC;
1159 return;
1160 }
1161 }
1162
1163 if (command == HPI_BUFFER_CMD_EXTERNAL
1164 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
1165 struct hpi_hostbuffer_status *status;
1166
1167 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
1168 buffer_size - 1)) {
1169 HPI_DEBUG_LOG(ERROR,
1170 "buffer size must be 2^N not %d\n",
1171 phm->u.d.u.buffer.buffer_size);
1172 phr->error = HPI_ERROR_INVALID_DATASIZE;
1173 return;
1174 }
1175
1176 phw->instream_host_buffer_size[phm->obj_index] =
1177 phm->u.d.u.buffer.buffer_size;
1178 status = &interface->instream_host_buffer_status[phm->
1179 obj_index];
1180 status->samples_processed = 0;
1181 status->stream_state = HPI_STATE_STOPPED;
1182 status->dSP_index = 0;
1183 status->host_index = status->dSP_index;
1184 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
1185
1186 hw_message(pao, phm, phr);
1187 if (phr->error
1188 && hpios_locked_mem_valid(&phw->
1189 instream_host_buffers[phm->obj_index])) {
1190 hpios_locked_mem_free(&phw->instream_host_buffers
1191 [phm->obj_index]);
1192 phw->instream_host_buffer_size[phm->obj_index] = 0;
1193 }
1194 }
1195}
1196
1197static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
1198 struct hpi_message *phm, struct hpi_response *phr)
1199{
1200 struct hpi_hw_obj *phw = pao->priv;
1201 struct bus_master_interface *interface = phw->p_interface_buffer;
1202 struct hpi_hostbuffer_status *status;
1203 u8 *p_bbm_data;
1204
1205 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1206 obj_index])) {
1207 if (hpios_locked_mem_get_virt_addr(&phw->
1208 instream_host_buffers[phm->obj_index],
1209 (void *)&p_bbm_data)) {
1210 phr->error = HPI_ERROR_INVALID_OPERATION;
1211 return;
1212 }
1213 status = &interface->instream_host_buffer_status[phm->
1214 obj_index];
1215 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1216 HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0);
1217 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
1218 phr->u.d.u.hostbuffer_info.p_status = status;
1219 } else {
1220 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1221 HPI_ISTREAM_HOSTBUFFER_GET_INFO,
1222 HPI_ERROR_INVALID_OPERATION);
1223 }
1224}
1225
1226static void instream_host_buffer_free(struct hpi_adapter_obj *pao,
1227 struct hpi_message *phm, struct hpi_response *phr)
1228{
1229 struct hpi_hw_obj *phw = pao->priv;
1230 u32 command = phm->u.d.u.buffer.command;
1231
1232 if (phw->instream_host_buffer_size[phm->obj_index]) {
1233 if (command == HPI_BUFFER_CMD_EXTERNAL
1234 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
1235 phw->instream_host_buffer_size[phm->obj_index] = 0;
1236 hw_message(pao, phm, phr);
1237 }
1238
1239 if (command == HPI_BUFFER_CMD_EXTERNAL
1240 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
1241 hpios_locked_mem_free(&phw->instream_host_buffers
1242 [phm->obj_index]);
1243
1244 } else {
1245 /* Should HPI_ERROR_INVALID_OPERATION be returned
1246 if no host buffer is allocated? */
1247 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1248 HPI_ISTREAM_HOSTBUFFER_FREE, 0);
1249
1250 }
1251
1252}
1253
1254static void instream_start(struct hpi_adapter_obj *pao,
1255 struct hpi_message *phm, struct hpi_response *phr)
1256{
1257 hw_message(pao, phm, phr);
1258}
1259
1260static long instream_get_bytes_available(struct hpi_hostbuffer_status *status)
1261{
1262 return (long)(status->dSP_index) - (long)(status->host_index);
1263}
1264
1265static void instream_read(struct hpi_adapter_obj *pao,
1266 struct hpi_message *phm, struct hpi_response *phr)
1267{
1268 struct hpi_hw_obj *phw = pao->priv;
1269 struct bus_master_interface *interface = phw->p_interface_buffer;
1270 struct hpi_hostbuffer_status *status;
1271 long data_available;
1272 u8 *p_bbm_data;
1273 long l_first_read;
1274 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
1275
1276 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1277 hw_message(pao, phm, phr);
1278 return;
1279 }
1280 hpi_init_response(phr, phm->object, phm->function, 0);
1281
1282 status = &interface->instream_host_buffer_status[phm->obj_index];
1283 data_available = instream_get_bytes_available(status);
1284 if (data_available < (long)phm->u.d.u.data.data_size) {
1285 phr->error = HPI_ERROR_INVALID_DATASIZE;
1286 return;
1287 }
1288
1289 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1290 obj_index])) {
1291 if (hpios_locked_mem_get_virt_addr(&phw->
1292 instream_host_buffers[phm->obj_index],
1293 (void *)&p_bbm_data)) {
1294 phr->error = HPI_ERROR_INVALID_OPERATION;
1295 return;
1296 }
1297
1298 /* either all data,
1299 or enough to fit from current to end of BBM buffer */
1300 l_first_read =
1301 min(phm->u.d.u.data.data_size,
1302 status->size_in_bytes -
1303 (status->host_index & (status->size_in_bytes - 1)));
1304
1305 memcpy(p_app_data,
1306 p_bbm_data +
1307 (status->host_index & (status->size_in_bytes - 1)),
1308 l_first_read);
1309 /* remaining data if any */
1310 memcpy(p_app_data + l_first_read, p_bbm_data,
1311 phm->u.d.u.data.data_size - l_first_read);
1312 }
1313 status->host_index += phm->u.d.u.data.data_size;
1314}
1315
1316static void instream_get_info(struct hpi_adapter_obj *pao,
1317 struct hpi_message *phm, struct hpi_response *phr)
1318{
1319 struct hpi_hw_obj *phw = pao->priv;
1320 struct bus_master_interface *interface = phw->p_interface_buffer;
1321 struct hpi_hostbuffer_status *status;
1322 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1323 hw_message(pao, phm, phr);
1324 return;
1325 }
1326
1327 status = &interface->instream_host_buffer_status[phm->obj_index];
1328
1329 hpi_init_response(phr, phm->object, phm->function, 0);
1330
1331 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1332 phr->u.d.u.stream_info.samples_transferred =
1333 status->samples_processed;
1334 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1335 phr->u.d.u.stream_info.data_available =
1336 instream_get_bytes_available(status);
1337 phr->u.d.u.stream_info.auxiliary_data_available =
1338 status->auxiliary_data_available;
1339}
1340
1341/*****************************************************************************/
1342/* LOW-LEVEL */
1343#define HPI6205_MAX_FILES_TO_LOAD 2
1344
1345static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
1346 u32 *pos_error_code)
1347{
1348 struct hpi_hw_obj *phw = pao->priv;
1349 struct dsp_code dsp_code;
1350 u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];
1351 u16 firmware_id = pao->pci.subsys_device_id;
1352 u32 temp;
1353 int dsp = 0, i = 0;
1354 u16 err = 0;
1355
1356 boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);
1357
1358 /* special cases where firmware_id != subsys ID */
1359 switch (firmware_id) {
1360 case HPI_ADAPTER_FAMILY_ASI(0x5000):
1361 boot_code_id[0] = firmware_id;
1362 firmware_id = 0;
1363 break;
1364 case HPI_ADAPTER_FAMILY_ASI(0x5300):
1365 case HPI_ADAPTER_FAMILY_ASI(0x5400):
1366 case HPI_ADAPTER_FAMILY_ASI(0x6300):
1367 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6400);
1368 break;
1369 case HPI_ADAPTER_FAMILY_ASI(0x5600):
1370 case HPI_ADAPTER_FAMILY_ASI(0x6500):
1371 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
1372 break;
1373 }
1374 boot_code_id[1] = firmware_id;
1375
1376 /* reset DSP by writing a 1 to the WARMRESET bit */
1377 temp = C6205_HDCR_WARMRESET;
1378 iowrite32(temp, phw->prHDCR);
1379 hpios_delay_micro_seconds(1000);
1380
1381 /* check that PCI i/f was configured by EEPROM */
1382 temp = ioread32(phw->prHSR);
1383 if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=
1384 C6205_HSR_EEREAD)
1385 return hpi6205_error(0, HPI6205_ERROR_6205_EEPROM);
1386 temp |= 0x04;
1387 /* disable PINTA interrupt */
1388 iowrite32(temp, phw->prHSR);
1389
1390 /* check control register reports PCI boot mode */
1391 temp = ioread32(phw->prHDCR);
1392 if (!(temp & C6205_HDCR_PCIBOOT))
1393 return hpi6205_error(0, HPI6205_ERROR_6205_REG);
1394
1395 /* try writing a couple of numbers to the DSP page register */
1396 /* and reading them back. */
1397 temp = 1;
1398 iowrite32(temp, phw->prDSPP);
1399 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1400 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1401 temp = 2;
1402 iowrite32(temp, phw->prDSPP);
1403 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1404 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1405 temp = 3;
1406 iowrite32(temp, phw->prDSPP);
1407 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1408 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1409 /* reset DSP page to the correct number */
1410 temp = 0;
1411 iowrite32(temp, phw->prDSPP);
1412 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1413 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1414 phw->dsp_page = 0;
1415
1416 /* release 6713 from reset before 6205 is bootloaded.
1417 This ensures that the EMIF is inactive,
1418 and the 6713 HPI gets the correct bootmode etc
1419 */
1420 if (boot_code_id[1] != 0) {
1421 /* DSP 1 is a C6713 */
1422 /* CLKX0 <- '1' release the C6205 bootmode pulldowns */
1423 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002202);
1424 hpios_delay_micro_seconds(100);
1425 /* Reset the 6713 #1 - revB */
1426 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
1427
1428 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1429 boot_loader_read_mem32(pao, 0, 0);
1430
1431 hpios_delay_micro_seconds(100);
1432 /* Release C6713 from reset - revB */
1433 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4);
1434 hpios_delay_micro_seconds(100);
1435 }
1436
1437 for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) {
1438 /* is there a DSP to load? */
1439 if (boot_code_id[dsp] == 0)
1440 continue;
1441
1442 err = boot_loader_config_emif(pao, dsp);
1443 if (err)
1444 return err;
1445
1446 err = boot_loader_test_internal_memory(pao, dsp);
1447 if (err)
1448 return err;
1449
1450 err = boot_loader_test_external_memory(pao, dsp);
1451 if (err)
1452 return err;
1453
1454 err = boot_loader_test_pld(pao, dsp);
1455 if (err)
1456 return err;
1457
1458 /* write the DSP code down into the DSPs memory */
1459 dsp_code.ps_dev = pao->pci.p_os_data;
1460 err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code,
1461 pos_error_code);
1462 if (err)
1463 return err;
1464
1465 while (1) {
1466 u32 length;
1467 u32 address;
1468 u32 type;
1469 u32 *pcode;
1470
1471 err = hpi_dsp_code_read_word(&dsp_code, &length);
1472 if (err)
1473 break;
1474 if (length == 0xFFFFFFFF)
1475 break; /* end of code */
1476
1477 err = hpi_dsp_code_read_word(&dsp_code, &address);
1478 if (err)
1479 break;
1480 err = hpi_dsp_code_read_word(&dsp_code, &type);
1481 if (err)
1482 break;
1483 err = hpi_dsp_code_read_block(length, &dsp_code,
1484 &pcode);
1485 if (err)
1486 break;
1487 for (i = 0; i < (int)length; i++) {
1488 err = boot_loader_write_mem32(pao, dsp,
1489 address, *pcode);
1490 if (err)
1491 break;
1492 /* dummy read every 4 words */
1493 /* for 6205 advisory 1.4.4 */
1494 if (i % 4 == 0)
1495 boot_loader_read_mem32(pao, dsp,
1496 address);
1497 pcode++;
1498 address += 4;
1499 }
1500
1501 }
1502 if (err) {
1503 hpi_dsp_code_close(&dsp_code);
1504 return err;
1505 }
1506
1507 /* verify code */
1508 hpi_dsp_code_rewind(&dsp_code);
1509 while (1) {
1510 u32 length = 0;
1511 u32 address = 0;
1512 u32 type = 0;
1513 u32 *pcode = NULL;
1514 u32 data = 0;
1515
1516 hpi_dsp_code_read_word(&dsp_code, &length);
1517 if (length == 0xFFFFFFFF)
1518 break; /* end of code */
1519
1520 hpi_dsp_code_read_word(&dsp_code, &address);
1521 hpi_dsp_code_read_word(&dsp_code, &type);
1522 hpi_dsp_code_read_block(length, &dsp_code, &pcode);
1523
1524 for (i = 0; i < (int)length; i++) {
1525 data = boot_loader_read_mem32(pao, dsp,
1526 address);
1527 if (data != *pcode) {
1528 err = 0;
1529 break;
1530 }
1531 pcode++;
1532 address += 4;
1533 }
1534 if (err)
1535 break;
1536 }
1537 hpi_dsp_code_close(&dsp_code);
1538 if (err)
1539 return err;
1540 }
1541
1542 /* After bootloading all DSPs, start DSP0 running
1543 * The DSP0 code will handle starting and synchronizing with its slaves
1544 */
1545 if (phw->p_interface_buffer) {
1546 /* we need to tell the card the physical PCI address */
1547 u32 physicalPC_iaddress;
1548 struct bus_master_interface *interface =
1549 phw->p_interface_buffer;
1550 u32 host_mailbox_address_on_dsp;
1551 u32 physicalPC_iaddress_verify = 0;
1552 int time_out = 10;
1553 /* set ack so we know when DSP is ready to go */
1554 /* (dwDspAck will be changed to HIF_RESET) */
1555 interface->dsp_ack = H620_HIF_UNKNOWN;
1556 wmb(); /* ensure ack is written before dsp writes back */
1557
1558 err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem,
1559 &physicalPC_iaddress);
1560
1561 /* locate the host mailbox on the DSP. */
1562 host_mailbox_address_on_dsp = 0x80000000;
1563 while ((physicalPC_iaddress != physicalPC_iaddress_verify)
1564 && time_out--) {
1565 err = boot_loader_write_mem32(pao, 0,
1566 host_mailbox_address_on_dsp,
1567 physicalPC_iaddress);
1568 physicalPC_iaddress_verify =
1569 boot_loader_read_mem32(pao, 0,
1570 host_mailbox_address_on_dsp);
1571 }
1572 }
1573 HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n");
1574 /* enable interrupts */
1575 temp = ioread32(phw->prHSR);
1576 temp &= ~(u32)C6205_HSR_INTAM;
1577 iowrite32(temp, phw->prHSR);
1578
1579 /* start code running... */
1580 temp = ioread32(phw->prHDCR);
1581 temp |= (u32)C6205_HDCR_DSPINT;
1582 iowrite32(temp, phw->prHDCR);
1583
1584 /* give the DSP 10ms to start up */
1585 hpios_delay_micro_seconds(10000);
1586 return err;
1587
1588}
1589
1590/*****************************************************************************/
1591/* Bootloader utility functions */
1592
1593static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
1594 u32 address)
1595{
1596 struct hpi_hw_obj *phw = pao->priv;
1597 u32 data = 0;
1598 __iomem u32 *p_data;
1599
1600 if (dsp_index == 0) {
1601 /* DSP 0 is always C6205 */
1602 if ((address >= 0x01800000) & (address < 0x02000000)) {
1603 /* BAR1 register access */
1604 p_data = pao->pci.ap_mem_base[1] +
1605 (address & 0x007fffff) /
1606 sizeof(*pao->pci.ap_mem_base[1]);
1607 /* HPI_DEBUG_LOG(WARNING,
1608 "BAR1 access %08x\n", dwAddress); */
1609 } else {
1610 u32 dw4M_page = address >> 22L;
1611 if (dw4M_page != phw->dsp_page) {
1612 phw->dsp_page = dw4M_page;
1613 /* *INDENT OFF* */
1614 iowrite32(phw->dsp_page, phw->prDSPP);
1615 /* *INDENT-ON* */
1616 }
1617 address &= 0x3fffff; /* address within 4M page */
1618 /* BAR0 memory access */
1619 p_data = pao->pci.ap_mem_base[0] +
1620 address / sizeof(u32);
1621 }
1622 data = ioread32(p_data);
1623 } else if (dsp_index == 1) {
1624 /* DSP 1 is a C6713 */
1625 u32 lsb;
1626 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1627 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1628 lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR);
1629 data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR);
1630 data = (data << 16) | (lsb & 0xFFFF);
1631 }
1632 return data;
1633}
1634
1635static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index,
1636 u32 address, u32 data)
1637{
1638 struct hpi_hw_obj *phw = pao->priv;
1639 u16 err = 0;
1640 __iomem u32 *p_data;
1641 /* u32 dwVerifyData=0; */
1642
1643 if (dsp_index == 0) {
1644 /* DSP 0 is always C6205 */
1645 if ((address >= 0x01800000) & (address < 0x02000000)) {
1646 /* BAR1 - DSP register access using */
1647 /* Non-prefetchable PCI access */
1648 p_data = pao->pci.ap_mem_base[1] +
1649 (address & 0x007fffff) /
1650 sizeof(*pao->pci.ap_mem_base[1]);
1651 } else {
1652 /* BAR0 access - all of DSP memory using */
1653 /* pre-fetchable PCI access */
1654 u32 dw4M_page = address >> 22L;
1655 if (dw4M_page != phw->dsp_page) {
1656 phw->dsp_page = dw4M_page;
1657 /* *INDENT-OFF* */
1658 iowrite32(phw->dsp_page, phw->prDSPP);
1659 /* *INDENT-ON* */
1660 }
1661 address &= 0x3fffff; /* address within 4M page */
1662 p_data = pao->pci.ap_mem_base[0] +
1663 address / sizeof(u32);
1664 }
1665 iowrite32(data, p_data);
1666 } else if (dsp_index == 1) {
1667 /* DSP 1 is a C6713 */
1668 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1669 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1670
1671 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1672 boot_loader_read_mem32(pao, 0, 0);
1673
1674 boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data);
1675 boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16);
1676
1677 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1678 boot_loader_read_mem32(pao, 0, 0);
1679 } else
1680 err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1681 return err;
1682}
1683
1684static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
1685{
1686 u16 err = 0;
1687
1688 if (dsp_index == 0) {
1689 u32 setting;
1690
1691 /* DSP 0 is always C6205 */
1692
1693 /* Set the EMIF */
1694 /* memory map of C6205 */
1695 /* 00000000-0000FFFF 16Kx32 internal program */
1696 /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */
1697
1698 /* EMIF config */
1699 /*------------ */
1700 /* Global EMIF control */
1701 boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779);
1702#define WS_OFS 28
1703#define WST_OFS 22
1704#define WH_OFS 20
1705#define RS_OFS 16
1706#define RST_OFS 8
1707#define MTYPE_OFS 4
1708#define RH_OFS 0
1709
1710 /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */
1711 setting = 0x00000030;
1712 boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
1713 if (setting != boot_loader_read_mem32(pao, dsp_index,
1714 0x01800008))
1715 return hpi6205_error(dsp_index,
1716 HPI6205_ERROR_DSP_EMIF);
1717
1718 /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
1719 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1720 /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */
1721 /* WST should be 71, but 63 is max possible */
1722 setting =
1723 (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) |
1724 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1725 (2L << MTYPE_OFS);
1726 boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
1727 if (setting != boot_loader_read_mem32(pao, dsp_index,
1728 0x01800004))
1729 return hpi6205_error(dsp_index,
1730 HPI6205_ERROR_DSP_EMIF);
1731
1732 /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
1733 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1734 /* plenty of wait states */
1735 setting =
1736 (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) |
1737 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1738 (2L << MTYPE_OFS);
1739 boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
1740 if (setting != boot_loader_read_mem32(pao, dsp_index,
1741 0x01800010))
1742 return hpi6205_error(dsp_index,
1743 HPI6205_ERROR_DSP_EMIF);
1744
1745 /* EMIF CE3 setup - 32 bit async. */
1746 /* This is the PLD on the ASI5000 cards only */
1747 setting =
1748 (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) |
1749 (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) |
1750 (2L << MTYPE_OFS);
1751 boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
1752 if (setting != boot_loader_read_mem32(pao, dsp_index,
1753 0x01800014))
1754 return hpi6205_error(dsp_index,
1755 HPI6205_ERROR_DSP_EMIF);
1756
1757 /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
1758 /* need to use this else DSP code crashes? */
1759 boot_loader_write_mem32(pao, dsp_index, 0x01800018,
1760 0x07117000);
1761
1762 /* EMIF SDRAM Refresh Timing */
1763 /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */
1764 boot_loader_write_mem32(pao, dsp_index, 0x0180001C,
1765 0x00000410);
1766
1767 } else if (dsp_index == 1) {
1768 /* test access to the C6713s HPI registers */
1769 u32 write_data = 0, read_data = 0, i = 0;
1770
1771 /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */
1772 write_data = 1;
1773 boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data);
1774 boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data);
1775 /* C67 HPI is on lower 16bits of 32bit EMIF */
1776 read_data =
1777 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);
1778 if (write_data != read_data) {
1779 err = hpi6205_error(dsp_index,
1780 HPI6205_ERROR_C6713_HPIC);
1781 HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,
1782 read_data);
1783
1784 return err;
1785 }
1786 /* HPIA - walking ones test */
1787 write_data = 1;
1788 for (i = 0; i < 32; i++) {
1789 boot_loader_write_mem32(pao, 0, HPIAL_ADDR,
1790 write_data);
1791 boot_loader_write_mem32(pao, 0, HPIAH_ADDR,
1792 (write_data >> 16));
1793 read_data =
1794 0xFFFF & boot_loader_read_mem32(pao, 0,
1795 HPIAL_ADDR);
1796 read_data =
1797 read_data | ((0xFFFF &
1798 boot_loader_read_mem32(pao, 0,
1799 HPIAH_ADDR))
1800 << 16);
1801 if (read_data != write_data) {
1802 err = hpi6205_error(dsp_index,
1803 HPI6205_ERROR_C6713_HPIA);
1804 HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",
1805 write_data, read_data);
1806 return err;
1807 }
1808 write_data = write_data << 1;
1809 }
1810
1811 /* setup C67x PLL
1812 * ** C6713 datasheet says we cannot program PLL from HPI,
1813 * and indeed if we try to set the PLL multiply from the HPI,
1814 * the PLL does not seem to lock, so we enable the PLL and
1815 * use the default multiply of x 7, which for a 27MHz clock
1816 * gives a DSP speed of 189MHz
1817 */
1818 /* bypass PLL */
1819 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000);
1820 hpios_delay_micro_seconds(1000);
1821 /* EMIF = 189/3=63MHz */
1822 boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002);
1823 /* peri = 189/2 */
1824 boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001);
1825 /* cpu = 189/1 */
1826 boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000);
1827 hpios_delay_micro_seconds(1000);
1828 /* ** SGT test to take GPO3 high when we start the PLL */
1829 /* and low when the delay is completed */
1830 /* FSX0 <- '1' (GPO3) */
1831 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A);
1832 /* PLL not bypassed */
1833 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001);
1834 hpios_delay_micro_seconds(1000);
1835 /* FSX0 <- '0' (GPO3) */
1836 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02);
1837
1838 /* 6205 EMIF CE1 resetup - 32 bit async. */
1839 /* Now 6713 #1 is running at 189MHz can reduce waitstates */
1840 boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */
1841 (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) |
1842 (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) |
1843 (2L << MTYPE_OFS));
1844
1845 hpios_delay_micro_seconds(1000);
1846
1847 /* check that we can read one of the PLL registers */
1848 /* PLL should not be bypassed! */
1849 if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)
1850 != 0x0001) {
1851 err = hpi6205_error(dsp_index,
1852 HPI6205_ERROR_C6713_PLL);
1853 return err;
1854 }
1855 /* setup C67x EMIF (note this is the only use of
1856 BAR1 via BootLoader_WriteMem32) */
1857 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,
1858 0x000034A8);
1859 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,
1860 0x00000030);
1861 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,
1862 0x001BDF29);
1863 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,
1864 0x47117000);
1865 boot_loader_write_mem32(pao, dsp_index,
1866 C6713_EMIF_SDRAMTIMING, 0x00000410);
1867
1868 hpios_delay_micro_seconds(1000);
1869 } else if (dsp_index == 2) {
1870 /* DSP 2 is a C6713 */
1871
1872 } else
1873 err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1874 return err;
1875}
1876
1877static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
1878 u32 start_address, u32 length)
1879{
1880 u32 i = 0, j = 0;
1881 u32 test_addr = 0;
1882 u32 test_data = 0, data = 0;
1883
1884 length = 1000;
1885
1886 /* for 1st word, test each bit in the 32bit word, */
1887 /* dwLength specifies number of 32bit words to test */
1888 /*for(i=0; i<dwLength; i++) */
1889 i = 0;
1890 {
1891 test_addr = start_address + i * 4;
1892 test_data = 0x00000001;
1893 for (j = 0; j < 32; j++) {
1894 boot_loader_write_mem32(pao, dsp_index, test_addr,
1895 test_data);
1896 data = boot_loader_read_mem32(pao, dsp_index,
1897 test_addr);
1898 if (data != test_data) {
1899 HPI_DEBUG_LOG(VERBOSE,
1900 "memtest error details "
1901 "%08x %08x %08x %i\n", test_addr,
1902 test_data, data, dsp_index);
1903 return 1; /* error */
1904 }
1905 test_data = test_data << 1;
1906 } /* for(j) */
1907 } /* for(i) */
1908
1909 /* for the next 100 locations test each location, leaving it as zero */
1910 /* write a zero to the next word in memory before we read */
1911 /* the previous write to make sure every memory location is unique */
1912 for (i = 0; i < 100; i++) {
1913 test_addr = start_address + i * 4;
1914 test_data = 0xA5A55A5A;
1915 boot_loader_write_mem32(pao, dsp_index, test_addr, test_data);
1916 boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0);
1917 data = boot_loader_read_mem32(pao, dsp_index, test_addr);
1918 if (data != test_data) {
1919 HPI_DEBUG_LOG(VERBOSE,
1920 "memtest error details "
1921 "%08x %08x %08x %i\n", test_addr, test_data,
1922 data, dsp_index);
1923 return 1; /* error */
1924 }
1925 /* leave location as zero */
1926 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1927 }
1928
1929 /* zero out entire memory block */
1930 for (i = 0; i < length; i++) {
1931 test_addr = start_address + i * 4;
1932 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1933 }
1934 return 0;
1935}
1936
1937static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
1938 int dsp_index)
1939{
1940 int err = 0;
1941 if (dsp_index == 0) {
1942 /* DSP 0 is a C6205 */
1943 /* 64K prog mem */
1944 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1945 0x10000);
1946 if (!err)
1947 /* 64K data mem */
1948 err = boot_loader_test_memory(pao, dsp_index,
1949 0x80000000, 0x10000);
1950 } else if ((dsp_index == 1) || (dsp_index == 2)) {
1951 /* DSP 1&2 are a C6713 */
1952 /* 192K internal mem */
1953 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1954 0x30000);
1955 if (!err)
1956 /* 64K internal mem / L2 cache */
1957 err = boot_loader_test_memory(pao, dsp_index,
1958 0x00030000, 0x10000);
1959 } else
1960 return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1961
1962 if (err)
1963 return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_INTMEM);
1964 else
1965 return 0;
1966}
1967
1968static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
1969 int dsp_index)
1970{
1971 u32 dRAM_start_address = 0;
1972 u32 dRAM_size = 0;
1973
1974 if (dsp_index == 0) {
1975 /* only test for SDRAM if an ASI5000 card */
1976 if (pao->pci.subsys_device_id == 0x5000) {
1977 /* DSP 0 is always C6205 */
1978 dRAM_start_address = 0x00400000;
1979 dRAM_size = 0x200000;
1980 /*dwDRAMinc=1024; */
1981 } else
1982 return 0;
1983 } else if ((dsp_index == 1) || (dsp_index == 2)) {
1984 /* DSP 1 is a C6713 */
1985 dRAM_start_address = 0x80000000;
1986 dRAM_size = 0x200000;
1987 /*dwDRAMinc=1024; */
1988 } else
1989 return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1990
1991 if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,
1992 dRAM_size))
1993 return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_EXTMEM);
1994 return 0;
1995}
1996
1997static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)
1998{
1999 u32 data = 0;
2000 if (dsp_index == 0) {
2001 /* only test for DSP0 PLD on ASI5000 card */
2002 if (pao->pci.subsys_device_id == 0x5000) {
2003 /* PLD is located at CE3=0x03000000 */
2004 data = boot_loader_read_mem32(pao, dsp_index,
2005 0x03000008);
2006 if ((data & 0xF) != 0x5)
2007 return hpi6205_error(dsp_index,
2008 HPI6205_ERROR_DSP_PLD);
2009 data = boot_loader_read_mem32(pao, dsp_index,
2010 0x0300000C);
2011 if ((data & 0xF) != 0xA)
2012 return hpi6205_error(dsp_index,
2013 HPI6205_ERROR_DSP_PLD);
2014 }
2015 } else if (dsp_index == 1) {
2016 /* DSP 1 is a C6713 */
2017 if (pao->pci.subsys_device_id == 0x8700) {
2018 /* PLD is located at CE1=0x90000000 */
2019 data = boot_loader_read_mem32(pao, dsp_index,
2020 0x90000010);
2021 if ((data & 0xFF) != 0xAA)
2022 return hpi6205_error(dsp_index,
2023 HPI6205_ERROR_DSP_PLD);
2024 /* 8713 - LED on */
2025 boot_loader_write_mem32(pao, dsp_index, 0x90000000,
2026 0x02);
2027 }
2028 }
2029 return 0;
2030}
2031
2032/** Transfer data to or from DSP
2033 nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA
2034*/
2035static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
2036 u32 data_size, int operation)
2037{
2038 struct hpi_hw_obj *phw = pao->priv;
2039 u32 data_transferred = 0;
2040 u16 err = 0;
2041#ifndef HPI6205_NO_HSR_POLL
2042 u32 time_out;
2043#endif
2044 u32 temp2;
2045 struct bus_master_interface *interface = phw->p_interface_buffer;
2046
2047 if (!p_data)
2048 return HPI_ERROR_INVALID_DATA_TRANSFER;
2049
2050 data_size &= ~3L; /* round data_size down to nearest 4 bytes */
2051
2052 /* make sure state is IDLE */
2053 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT))
2054 return HPI_ERROR_DSP_HARDWARE;
2055
2056 while (data_transferred < data_size) {
2057 u32 this_copy = data_size - data_transferred;
2058
2059 if (this_copy > HPI6205_SIZEOF_DATA)
2060 this_copy = HPI6205_SIZEOF_DATA;
2061
2062 if (operation == H620_HIF_SEND_DATA)
2063 memcpy((void *)&interface->u.b_data[0],
2064 &p_data[data_transferred], this_copy);
2065
2066 interface->transfer_size_in_bytes = this_copy;
2067
2068#ifdef HPI6205_NO_HSR_POLL
2069 /* DSP must change this back to nOperation */
2070 interface->dsp_ack = H620_HIF_IDLE;
2071#endif
2072
2073 send_dsp_command(phw, operation);
2074
2075#ifdef HPI6205_NO_HSR_POLL
2076 temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT);
2077 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2078 HPI6205_TIMEOUT - temp2, this_copy);
2079
2080 if (!temp2) {
2081 /* timed out */
2082 HPI_DEBUG_LOG(ERROR,
2083 "timed out waiting for " "state %d got %d\n",
2084 operation, interface->dsp_ack);
2085
2086 break;
2087 }
2088#else
2089 /* spin waiting on the result */
2090 time_out = HPI6205_TIMEOUT;
2091 temp2 = 0;
2092 while ((temp2 == 0) && time_out--) {
2093 /* give 16k bus mastering transfer time to happen */
2094 /*(16k / 132Mbytes/s = 122usec) */
2095 hpios_delay_micro_seconds(20);
2096 temp2 = ioread32(phw->prHSR);
2097 temp2 &= C6205_HSR_INTSRC;
2098 }
2099 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2100 HPI6205_TIMEOUT - time_out, this_copy);
2101 if (temp2 == C6205_HSR_INTSRC) {
2102 HPI_DEBUG_LOG(VERBOSE,
2103 "interrupt from HIF <data> OK\n");
2104 /*
2105 if(interface->dwDspAck != nOperation) {
2106 HPI_DEBUG_LOG(DEBUG("interface->dwDspAck=%d,
2107 expected %d \n",
2108 interface->dwDspAck,nOperation);
2109 }
2110 */
2111 }
2112/* need to handle this differently... */
2113 else {
2114 HPI_DEBUG_LOG(ERROR,
2115 "interrupt from HIF <data> BAD\n");
2116 err = HPI_ERROR_DSP_HARDWARE;
2117 }
2118
2119 /* reset the interrupt from the DSP */
2120 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2121#endif
2122 if (operation == H620_HIF_GET_DATA)
2123 memcpy(&p_data[data_transferred],
2124 (void *)&interface->u.b_data[0], this_copy);
2125
2126 data_transferred += this_copy;
2127 }
2128 if (interface->dsp_ack != operation)
2129 HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n",
2130 interface->dsp_ack, operation);
2131 /* err=HPI_ERROR_DSP_HARDWARE; */
2132
2133 send_dsp_command(phw, H620_HIF_IDLE);
2134
2135 return err;
2136}
2137
2138/* wait for up to timeout_us microseconds for the DSP
2139 to signal state by DMA into dwDspAck
2140*/
2141static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
2142{
2143 struct bus_master_interface *interface = phw->p_interface_buffer;
2144 int t = timeout_us / 4;
2145
2146 rmb(); /* ensure interface->dsp_ack is up to date */
2147 while ((interface->dsp_ack != state) && --t) {
2148 hpios_delay_micro_seconds(4);
2149 rmb(); /* DSP changes dsp_ack by DMA */
2150 }
2151
2152 /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */
2153 return t * 4;
2154}
2155
2156/* set the busmaster interface to cmd, then interrupt the DSP */
2157static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
2158{
2159 struct bus_master_interface *interface = phw->p_interface_buffer;
2160
2161 u32 r;
2162
2163 interface->host_cmd = cmd;
2164 wmb(); /* DSP gets state by DMA, make sure it is written to memory */
2165 /* before we interrupt the DSP */
2166 r = ioread32(phw->prHDCR);
2167 r |= (u32)C6205_HDCR_DSPINT;
2168 iowrite32(r, phw->prHDCR);
2169 r &= ~(u32)C6205_HDCR_DSPINT;
2170 iowrite32(r, phw->prHDCR);
2171}
2172
2173static unsigned int message_count;
2174
2175static u16 message_response_sequence(struct hpi_adapter_obj *pao,
2176 struct hpi_message *phm, struct hpi_response *phr)
2177{
2178#ifndef HPI6205_NO_HSR_POLL
2179 u32 temp2;
2180#endif
2181 u32 time_out, time_out2;
2182 struct hpi_hw_obj *phw = pao->priv;
2183 struct bus_master_interface *interface = phw->p_interface_buffer;
2184 u16 err = 0;
2185
2186 message_count++;
2187 /* Assume buffer of type struct bus_master_interface
2188 is allocated "noncacheable" */
2189
2190 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2191 HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");
2192 return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT);
2193 }
2194 interface->u.message_buffer = *phm;
2195 /* signal we want a response */
2196 send_dsp_command(phw, H620_HIF_GET_RESP);
2197
2198 time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);
2199
2200 if (time_out2 == 0) {
2201 HPI_DEBUG_LOG(ERROR,
2202 "(%u) timed out waiting for " "GET_RESP state [%x]\n",
2203 message_count, interface->dsp_ack);
2204 } else {
2205 HPI_DEBUG_LOG(VERBOSE,
2206 "(%u) transition to GET_RESP after %u\n",
2207 message_count, HPI6205_TIMEOUT - time_out2);
2208 }
2209 /* spin waiting on HIF interrupt flag (end of msg process) */
2210 time_out = HPI6205_TIMEOUT;
2211
2212#ifndef HPI6205_NO_HSR_POLL
2213 temp2 = 0;
2214 while ((temp2 == 0) && --time_out) {
2215 temp2 = ioread32(phw->prHSR);
2216 temp2 &= C6205_HSR_INTSRC;
2217 hpios_delay_micro_seconds(1);
2218 }
2219 if (temp2 == C6205_HSR_INTSRC) {
2220 rmb(); /* ensure we see latest value for dsp_ack */
2221 if ((interface->dsp_ack != H620_HIF_GET_RESP)) {
2222 HPI_DEBUG_LOG(DEBUG,
2223 "(%u)interface->dsp_ack(0x%x) != "
2224 "H620_HIF_GET_RESP, t=%u\n", message_count,
2225 interface->dsp_ack,
2226 HPI6205_TIMEOUT - time_out);
2227 } else {
2228 HPI_DEBUG_LOG(VERBOSE,
2229 "(%u)int with GET_RESP after %u\n",
2230 message_count, HPI6205_TIMEOUT - time_out);
2231 }
2232
2233 } else {
2234 /* can we do anything else in response to the error ? */
2235 HPI_DEBUG_LOG(ERROR,
2236 "interrupt from HIF module BAD (function %x)\n",
2237 phm->function);
2238 }
2239
2240 /* reset the interrupt from the DSP */
2241 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2242#endif
2243
2244 /* read the result */
2245 if (time_out != 0)
2246 *phr = interface->u.response_buffer;
2247
2248 /* set interface back to idle */
2249 send_dsp_command(phw, H620_HIF_IDLE);
2250
2251 if ((time_out == 0) || (time_out2 == 0)) {
2252 HPI_DEBUG_LOG(DEBUG, "something timed out!\n");
2253 return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_TIMEOUT);
2254 }
2255 /* special case for adapter close - */
2256 /* wait for the DSP to indicate it is idle */
2257 if (phm->function == HPI_ADAPTER_CLOSE) {
2258 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2259 HPI_DEBUG_LOG(DEBUG,
2260 "timeout waiting for idle "
2261 "(on adapter_close)\n");
2262 return hpi6205_error(0,
2263 HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT);
2264 }
2265 }
2266 err = hpi_validate_response(phm, phr);
2267 return err;
2268}
2269
2270static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
2271 struct hpi_response *phr)
2272{
2273
2274 u16 err = 0;
2275
2276 hpios_dsplock_lock(pao);
2277
2278 err = message_response_sequence(pao, phm, phr);
2279
2280 /* maybe an error response */
2281 if (err) {
2282 /* something failed in the HPI/DSP interface */
2283 phr->error = err;
2284 pao->dsp_crashed++;
2285
2286 /* just the header of the response is valid */
2287 phr->size = sizeof(struct hpi_response_header);
2288 goto err;
2289 } else
2290 pao->dsp_crashed = 0;
2291
2292 if (phr->error != 0) /* something failed in the DSP */
2293 goto err;
2294
2295 switch (phm->function) {
2296 case HPI_OSTREAM_WRITE:
2297 case HPI_ISTREAM_ANC_WRITE:
2298 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2299 phm->u.d.u.data.data_size, H620_HIF_SEND_DATA);
2300 break;
2301
2302 case HPI_ISTREAM_READ:
2303 case HPI_OSTREAM_ANC_READ:
2304 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2305 phm->u.d.u.data.data_size, H620_HIF_GET_DATA);
2306 break;
2307
2308 case HPI_CONTROL_SET_STATE:
2309 if (phm->object == HPI_OBJ_CONTROLEX
2310 && phm->u.cx.attribute == HPI_COBRANET_SET_DATA)
2311 err = hpi6205_transfer_data(pao,
2312 phm->u.cx.u.cobranet_bigdata.pb_data,
2313 phm->u.cx.u.cobranet_bigdata.byte_count,
2314 H620_HIF_SEND_DATA);
2315 break;
2316
2317 case HPI_CONTROL_GET_STATE:
2318 if (phm->object == HPI_OBJ_CONTROLEX
2319 && phm->u.cx.attribute == HPI_COBRANET_GET_DATA)
2320 err = hpi6205_transfer_data(pao,
2321 phm->u.cx.u.cobranet_bigdata.pb_data,
2322 phr->u.cx.u.cobranet_data.byte_count,
2323 H620_HIF_GET_DATA);
2324 break;
2325 }
2326 phr->error = err;
2327
2328err:
2329 hpios_dsplock_unlock(pao);
2330
2331 return;
2332}
diff --git a/sound/pci/asihpi/hpi6205.h b/sound/pci/asihpi/hpi6205.h
new file mode 100644
index 000000000000..1adae0857cda
--- /dev/null
+++ b/sound/pci/asihpi/hpi6205.h
@@ -0,0 +1,93 @@
1/*****************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Host Interface module for an ASI6205 based
20bus mastering PCI adapter.
21
22Copyright AudioScience, Inc., 2003
23******************************************************************************/
24
25#ifndef _HPI6205_H_
26#define _HPI6205_H_
27
28/* transitional conditional compile shared between host and DSP */
29/* #define HPI6205_NO_HSR_POLL */
30
31#include "hpi_internal.h"
32
33/***********************************************************
34 Defines used for basic messaging
35************************************************************/
36#define H620_HIF_RESET 0
37#define H620_HIF_IDLE 1
38#define H620_HIF_GET_RESP 2
39#define H620_HIF_DATA_DONE 3
40#define H620_HIF_DATA_MASK 0x10
41#define H620_HIF_SEND_DATA 0x14
42#define H620_HIF_GET_DATA 0x15
43#define H620_HIF_UNKNOWN 0x0000ffff
44
45/***********************************************************
46 Types used for mixer control caching
47************************************************************/
48
49#define H620_MAX_ISTREAMS 32
50#define H620_MAX_OSTREAMS 32
51#define HPI_NMIXER_CONTROLS 2048
52
53/*********************************************************************
54This is used for dynamic control cache allocation
55**********************************************************************/
56struct controlcache_6205 {
57 u32 number_of_controls;
58 u32 physical_address32;
59 u32 size_in_bytes;
60};
61
62/*********************************************************************
63This is used for dynamic allocation of async event array
64**********************************************************************/
65struct async_event_buffer_6205 {
66 u32 physical_address32;
67 u32 spare;
68 struct hpi_fifo_buffer b;
69};
70
71/***********************************************************
72The Host located memory buffer that the 6205 will bus master
73in and out of.
74************************************************************/
75#define HPI6205_SIZEOF_DATA (16*1024)
76struct bus_master_interface {
77 u32 host_cmd;
78 u32 dsp_ack;
79 u32 transfer_size_in_bytes;
80 union {
81 struct hpi_message message_buffer;
82 struct hpi_response response_buffer;
83 u8 b_data[HPI6205_SIZEOF_DATA];
84 } u;
85 struct controlcache_6205 control_cache;
86 struct async_event_buffer_6205 async_buffer;
87 struct hpi_hostbuffer_status
88 instream_host_buffer_status[H620_MAX_ISTREAMS];
89 struct hpi_hostbuffer_status
90 outstream_host_buffer_status[H620_MAX_OSTREAMS];
91};
92
93#endif
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
new file mode 100644
index 000000000000..f1cd6f1a0d44
--- /dev/null
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -0,0 +1,1641 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19HPI internal definitions
20
21(C) Copyright AudioScience Inc. 1996-2009
22******************************************************************************/
23
24#ifndef _HPI_INTERNAL_H_
25#define _HPI_INTERNAL_H_
26
27#include "hpi.h"
28/** maximum number of memory regions mapped to an adapter */
29#define HPI_MAX_ADAPTER_MEM_SPACES (2)
30
31/* Each OS needs its own hpios.h, or specific define as above */
32#include "hpios.h"
33
34/* physical memory allocation */
35void hpios_locked_mem_init(void
36 );
37void hpios_locked_mem_free_all(void
38 );
39#define hpios_locked_mem_prepare(a, b, c, d);
40#define hpios_locked_mem_unprepare(a)
41
42/** Allocate and map an area of locked memory for bus master DMA operations.
43
44On success, *pLockedMemeHandle is a valid handle, and 0 is returned
45On error *pLockedMemHandle marked invalid, non-zero returned.
46
47If this function succeeds, then HpiOs_LockedMem_GetVirtAddr() and
48HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle.
49*/
50u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle,
51 /**< memory handle */
52 u32 size, /**< size in bytes to allocate */
53 struct pci_dev *p_os_reference
54 /**< OS specific data required for memory allocation */
55 );
56
57/** Free mapping and memory represented by LockedMemHandle
58
59Frees any resources, then invalidates the handle.
60Returns 0 on success, 1 if handle is invalid.
61
62*/
63u16 hpios_locked_mem_free(struct consistent_dma_area *locked_mem_handle);
64
65/** Get the physical PCI address of memory represented by LockedMemHandle.
66
67If handle is invalid *pPhysicalAddr is set to zero and return 1
68*/
69u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area
70 *locked_mem_handle, u32 *p_physical_addr);
71
72/** Get the CPU address of of memory represented by LockedMemHandle.
73
74If handle is NULL *ppvVirtualAddr is set to NULL and return 1
75*/
76u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area
77 *locked_mem_handle, void **ppv_virtual_addr);
78
79/** Check that handle is valid
80i.e it represents a valid memory area
81*/
82u16 hpios_locked_mem_valid(struct consistent_dma_area *locked_mem_handle);
83
84/* timing/delay */
85void hpios_delay_micro_seconds(u32 num_micro_sec);
86
87struct hpi_message;
88struct hpi_response;
89
90typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *);
91
92/* If the assert fails, compiler complains
93 something like size of array `msg' is negative.
94 Unlike linux BUILD_BUG_ON, this works outside function scope.
95*/
96#define compile_time_assert(cond, msg) \
97 typedef char ASSERT_##msg[(cond) ? 1 : -1]
98
99/*/////////////////////////////////////////////////////////////////////////// */
100/* Private HPI Entity related definitions */
101
102#define STR_SIZE_FIELD_MAX 65535U
103#define STR_TYPE_FIELD_MAX 255U
104#define STR_ROLE_FIELD_MAX 255U
105
106struct hpi_entity_str {
107 uint16_t size;
108 uint8_t type;
109 uint8_t role;
110};
111
112#if defined(_MSC_VER)
113#pragma warning(push)
114#pragma warning(disable : 4200)
115#endif
116
117struct hpi_entity {
118 struct hpi_entity_str header;
119#if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008))
120 /* DSP C6000 compiler v6.0.8 and lower
121 do not support flexible array member */
122 uint8_t value[];
123#else
124 /* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */
125#define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE
126 uint8_t value[1];
127#endif
128};
129
130#if defined(_MSC_VER)
131#pragma warning(pop)
132#endif
133
134/******************************************* bus types */
135enum HPI_BUSES {
136 HPI_BUS_ISAPNP = 1,
137 HPI_BUS_PCI = 2,
138 HPI_BUS_USB = 3,
139 HPI_BUS_NET = 4
140};
141
142/******************************************* CONTROL ATTRIBUTES ****/
143/* (in order of control type ID */
144
145 /* This allows for 255 control types, 256 unique attributes each */
146#define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
147
148/* Get the sub-index of the attribute for a control type */
149#define HPI_CTL_ATTR_INDEX(i) (i&0xff)
150
151/* Generic control attributes. */
152
153/** Enable a control.
1540=disable, 1=enable
155\note generic to all mixer plugins?
156*/
157#define HPI_GENERIC_ENABLE HPI_CTL_ATTR(GENERIC, 1)
158
159/** Enable event generation for a control.
1600=disable, 1=enable
161\note generic to all controls that can generate events
162*/
163#define HPI_GENERIC_EVENT_ENABLE HPI_CTL_ATTR(GENERIC, 2)
164
165/* Volume Control attributes */
166#define HPI_VOLUME_GAIN HPI_CTL_ATTR(VOLUME, 1)
167#define HPI_VOLUME_AUTOFADE HPI_CTL_ATTR(VOLUME, 2)
168
169/** For HPI_ControlQuery() to get the number of channels of a volume control*/
170#define HPI_VOLUME_NUM_CHANNELS HPI_CTL_ATTR(VOLUME, 6)
171#define HPI_VOLUME_RANGE HPI_CTL_ATTR(VOLUME, 10)
172
173/** Level Control attributes */
174#define HPI_LEVEL_GAIN HPI_CTL_ATTR(LEVEL, 1)
175#define HPI_LEVEL_RANGE HPI_CTL_ATTR(LEVEL, 10)
176
177/* Meter Control attributes */
178/** return RMS signal level */
179#define HPI_METER_RMS HPI_CTL_ATTR(METER, 1)
180/** return peak signal level */
181#define HPI_METER_PEAK HPI_CTL_ATTR(METER, 2)
182/** ballistics for ALL rms meters on adapter */
183#define HPI_METER_RMS_BALLISTICS HPI_CTL_ATTR(METER, 3)
184/** ballistics for ALL peak meters on adapter */
185#define HPI_METER_PEAK_BALLISTICS HPI_CTL_ATTR(METER, 4)
186
187/** For HPI_ControlQuery() to get the number of channels of a meter control*/
188#define HPI_METER_NUM_CHANNELS HPI_CTL_ATTR(METER, 5)
189
190/* Multiplexer control attributes */
191#define HPI_MULTIPLEXER_SOURCE HPI_CTL_ATTR(MULTIPLEXER, 1)
192#define HPI_MULTIPLEXER_QUERYSOURCE HPI_CTL_ATTR(MULTIPLEXER, 2)
193
194/** AES/EBU transmitter control attributes */
195/** AESEBU or SPDIF */
196#define HPI_AESEBUTX_FORMAT HPI_CTL_ATTR(AESEBUTX, 1)
197#define HPI_AESEBUTX_SAMPLERATE HPI_CTL_ATTR(AESEBUTX, 3)
198#define HPI_AESEBUTX_CHANNELSTATUS HPI_CTL_ATTR(AESEBUTX, 4)
199#define HPI_AESEBUTX_USERDATA HPI_CTL_ATTR(AESEBUTX, 5)
200
201/** AES/EBU receiver control attributes */
202#define HPI_AESEBURX_FORMAT HPI_CTL_ATTR(AESEBURX, 1)
203#define HPI_AESEBURX_ERRORSTATUS HPI_CTL_ATTR(AESEBURX, 2)
204#define HPI_AESEBURX_SAMPLERATE HPI_CTL_ATTR(AESEBURX, 3)
205#define HPI_AESEBURX_CHANNELSTATUS HPI_CTL_ATTR(AESEBURX, 4)
206#define HPI_AESEBURX_USERDATA HPI_CTL_ATTR(AESEBURX, 5)
207
208/** \defgroup tuner_defs Tuners
209\{
210*/
211/** \defgroup tuner_attrs Tuner control attributes
212\{
213*/
214#define HPI_TUNER_BAND HPI_CTL_ATTR(TUNER, 1)
215#define HPI_TUNER_FREQ HPI_CTL_ATTR(TUNER, 2)
216#define HPI_TUNER_LEVEL HPI_CTL_ATTR(TUNER, 3)
217#define HPI_TUNER_AUDIOMUTE HPI_CTL_ATTR(TUNER, 4)
218/* use TUNER_STATUS instead */
219#define HPI_TUNER_VIDEO_STATUS HPI_CTL_ATTR(TUNER, 5)
220#define HPI_TUNER_GAIN HPI_CTL_ATTR(TUNER, 6)
221#define HPI_TUNER_STATUS HPI_CTL_ATTR(TUNER, 7)
222#define HPI_TUNER_MODE HPI_CTL_ATTR(TUNER, 8)
223/** RDS data. */
224#define HPI_TUNER_RDS HPI_CTL_ATTR(TUNER, 9)
225/** Audio pre-emphasis. */
226#define HPI_TUNER_DEEMPHASIS HPI_CTL_ATTR(TUNER, 10)
227/** HD Radio tuner program control. */
228#define HPI_TUNER_PROGRAM HPI_CTL_ATTR(TUNER, 11)
229/** HD Radio tuner digital signal quality. */
230#define HPI_TUNER_HDRADIO_SIGNAL_QUALITY HPI_CTL_ATTR(TUNER, 12)
231/** HD Radio SDK firmware version. */
232#define HPI_TUNER_HDRADIO_SDK_VERSION HPI_CTL_ATTR(TUNER, 13)
233/** HD Radio DSP firmware version. */
234#define HPI_TUNER_HDRADIO_DSP_VERSION HPI_CTL_ATTR(TUNER, 14)
235
236/** \} */
237
238/** \defgroup pads_attrs Tuner PADs control attributes
239\{
240*/
241/** The text string containing the station/channel combination. */
242#define HPI_PAD_CHANNEL_NAME HPI_CTL_ATTR(PAD, 1)
243/** The text string containing the artist. */
244#define HPI_PAD_ARTIST HPI_CTL_ATTR(PAD, 2)
245/** The text string containing the title. */
246#define HPI_PAD_TITLE HPI_CTL_ATTR(PAD, 3)
247/** The text string containing the comment. */
248#define HPI_PAD_COMMENT HPI_CTL_ATTR(PAD, 4)
249/** The integer containing the PTY code. */
250#define HPI_PAD_PROGRAM_TYPE HPI_CTL_ATTR(PAD, 5)
251/** The integer containing the program identification. */
252#define HPI_PAD_PROGRAM_ID HPI_CTL_ATTR(PAD, 6)
253/** The integer containing whether traffic information is supported.
254Contains either 1 or 0. */
255#define HPI_PAD_TA_SUPPORT HPI_CTL_ATTR(PAD, 7)
256/** The integer containing whether traffic announcement is in progress.
257Contains either 1 or 0. */
258#define HPI_PAD_TA_ACTIVE HPI_CTL_ATTR(PAD, 8)
259/** \} */
260/** \} */
261
262/* VOX control attributes */
263#define HPI_VOX_THRESHOLD HPI_CTL_ATTR(VOX, 1)
264
265/*?? channel mode used hpi_multiplexer_source attribute == 1 */
266#define HPI_CHANNEL_MODE_MODE HPI_CTL_ATTR(CHANNEL_MODE, 1)
267
268/** \defgroup channel_modes Channel Modes
269Used for HPI_ChannelModeSet/Get()
270\{
271*/
272/** Left channel out = left channel in, Right channel out = right channel in. */
273#define HPI_CHANNEL_MODE_NORMAL 1
274/** Left channel out = right channel in, Right channel out = left channel in. */
275#define HPI_CHANNEL_MODE_SWAP 2
276/** Left channel out = left channel in, Right channel out = left channel in. */
277#define HPI_CHANNEL_MODE_LEFT_TO_STEREO 3
278/** Left channel out = right channel in, Right channel out = right channel in.*/
279#define HPI_CHANNEL_MODE_RIGHT_TO_STEREO 4
280/** Left channel out = (left channel in + right channel in)/2,
281 Right channel out = mute. */
282#define HPI_CHANNEL_MODE_STEREO_TO_LEFT 5
283/** Left channel out = mute,
284 Right channel out = (right channel in + left channel in)/2. */
285#define HPI_CHANNEL_MODE_STEREO_TO_RIGHT 6
286#define HPI_CHANNEL_MODE_LAST 6
287/** \} */
288
289/* Bitstream control set attributes */
290#define HPI_BITSTREAM_DATA_POLARITY HPI_CTL_ATTR(BITSTREAM, 1)
291#define HPI_BITSTREAM_CLOCK_EDGE HPI_CTL_ATTR(BITSTREAM, 2)
292#define HPI_BITSTREAM_CLOCK_SOURCE HPI_CTL_ATTR(BITSTREAM, 3)
293
294#define HPI_POLARITY_POSITIVE 0
295#define HPI_POLARITY_NEGATIVE 1
296
297/* Bitstream control get attributes */
298#define HPI_BITSTREAM_ACTIVITY 1
299
300/* SampleClock control attributes */
301#define HPI_SAMPLECLOCK_SOURCE HPI_CTL_ATTR(SAMPLECLOCK, 1)
302#define HPI_SAMPLECLOCK_SAMPLERATE HPI_CTL_ATTR(SAMPLECLOCK, 2)
303#define HPI_SAMPLECLOCK_SOURCE_INDEX HPI_CTL_ATTR(SAMPLECLOCK, 3)
304#define HPI_SAMPLECLOCK_LOCAL_SAMPLERATE\
305 HPI_CTL_ATTR(SAMPLECLOCK, 4)
306#define HPI_SAMPLECLOCK_AUTO HPI_CTL_ATTR(SAMPLECLOCK, 5)
307#define HPI_SAMPLECLOCK_LOCAL_LOCK HPI_CTL_ATTR(SAMPLECLOCK, 6)
308
309/* Microphone control attributes */
310#define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1)
311
312/** Equalizer control attributes
313*/
314/** Used to get number of filters in an EQ. (Can't set) */
315#define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1)
316/** Set/get the filter by type, freq, Q, gain */
317#define HPI_EQUALIZER_FILTER HPI_CTL_ATTR(EQUALIZER, 2)
318/** Get the biquad coefficients */
319#define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3)
320
321#define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1)
322
323/* Cobranet control attributes.
324 MUST be distinct from all other control attributes.
325 This is so that host side processing can easily identify a Cobranet control
326 and apply additional host side operations (like copying data) as required.
327*/
328#define HPI_COBRANET_SET HPI_CTL_ATTR(COBRANET, 1)
329#define HPI_COBRANET_GET HPI_CTL_ATTR(COBRANET, 2)
330#define HPI_COBRANET_SET_DATA HPI_CTL_ATTR(COBRANET, 3)
331#define HPI_COBRANET_GET_DATA HPI_CTL_ATTR(COBRANET, 4)
332#define HPI_COBRANET_GET_STATUS HPI_CTL_ATTR(COBRANET, 5)
333#define HPI_COBRANET_SEND_PACKET HPI_CTL_ATTR(COBRANET, 6)
334#define HPI_COBRANET_GET_PACKET HPI_CTL_ATTR(COBRANET, 7)
335
336/*------------------------------------------------------------
337 Cobranet Chip Bridge - copied from HMI.H
338------------------------------------------------------------*/
339#define HPI_COBRANET_HMI_cobra_bridge 0x20000
340#define HPI_COBRANET_HMI_cobra_bridge_tx_pkt_buf \
341 (HPI_COBRANET_HMI_cobra_bridge + 0x1000)
342#define HPI_COBRANET_HMI_cobra_bridge_rx_pkt_buf \
343 (HPI_COBRANET_HMI_cobra_bridge + 0x2000)
344#define HPI_COBRANET_HMI_cobra_if_table1 0x110000
345#define HPI_COBRANET_HMI_cobra_if_phy_address \
346 (HPI_COBRANET_HMI_cobra_if_table1 + 0xd)
347#define HPI_COBRANET_HMI_cobra_protocolIP 0x72000
348#define HPI_COBRANET_HMI_cobra_ip_mon_currentIP \
349 (HPI_COBRANET_HMI_cobra_protocolIP + 0x0)
350#define HPI_COBRANET_HMI_cobra_ip_mon_staticIP \
351 (HPI_COBRANET_HMI_cobra_protocolIP + 0x2)
352#define HPI_COBRANET_HMI_cobra_sys 0x100000
353#define HPI_COBRANET_HMI_cobra_sys_desc \
354 (HPI_COBRANET_HMI_cobra_sys + 0x0)
355#define HPI_COBRANET_HMI_cobra_sys_objectID \
356 (HPI_COBRANET_HMI_cobra_sys + 0x100)
357#define HPI_COBRANET_HMI_cobra_sys_contact \
358 (HPI_COBRANET_HMI_cobra_sys + 0x200)
359#define HPI_COBRANET_HMI_cobra_sys_name \
360 (HPI_COBRANET_HMI_cobra_sys + 0x300)
361#define HPI_COBRANET_HMI_cobra_sys_location \
362 (HPI_COBRANET_HMI_cobra_sys + 0x400)
363
364/*------------------------------------------------------------
365 Cobranet Chip Status bits
366------------------------------------------------------------*/
367#define HPI_COBRANET_HMI_STATUS_RXPACKET 2
368#define HPI_COBRANET_HMI_STATUS_TXPACKET 3
369
370/*------------------------------------------------------------
371 Ethernet header size
372------------------------------------------------------------*/
373#define HPI_ETHERNET_HEADER_SIZE (16)
374
375/* These defines are used to fill in protocol information for an Ethernet packet
376 sent using HMI on CS18102 */
377/** ID supplied by Cirrius for ASI packets. */
378#define HPI_ETHERNET_PACKET_ID 0x85
379/** Simple packet - no special routing required */
380#define HPI_ETHERNET_PACKET_V1 0x01
381/** This packet must make its way to the host across the HPI interface */
382#define HPI_ETHERNET_PACKET_HOSTED_VIA_HMI 0x20
383/** This packet must make its way to the host across the HPI interface */
384#define HPI_ETHERNET_PACKET_HOSTED_VIA_HMI_V1 0x21
385/** This packet must make its way to the host across the HPI interface */
386#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI 0x40
387/** This packet must make its way to the host across the HPI interface */
388#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41
389
390#define HPI_ETHERNET_UDP_PORT (44600) /*!< UDP messaging port */
391
392/** Base network time out is set to 100 milli-seconds. */
393#define HPI_ETHERNET_TIMEOUT_MS (100)
394
395/** \defgroup tonedet_attr Tonedetector attributes
396\{
397Used by HPI_ToneDetector_Set() and HPI_ToneDetector_Get()
398*/
399
400/** Set the threshold level of a tonedetector,
401Threshold is a -ve number in units of dB/100,
402*/
403#define HPI_TONEDETECTOR_THRESHOLD HPI_CTL_ATTR(TONEDETECTOR, 1)
404
405/** Get the current state of tonedetection
406The result is a bitmap of detected tones. pairs of bits represent the left
407and right channels, with left channel in LSB.
408The lowest frequency detector state is in the LSB
409*/
410#define HPI_TONEDETECTOR_STATE HPI_CTL_ATTR(TONEDETECTOR, 2)
411
412/** Get the frequency of a tonedetector band.
413*/
414#define HPI_TONEDETECTOR_FREQUENCY HPI_CTL_ATTR(TONEDETECTOR, 3)
415
416/**\}*/
417
418/** \defgroup silencedet_attr SilenceDetector attributes
419\{
420*/
421
422/** Get the current state of tonedetection
423The result is a bitmap with 1s for silent channels. Left channel is in LSB
424*/
425#define HPI_SILENCEDETECTOR_STATE \
426 HPI_CTL_ATTR(SILENCEDETECTOR, 2)
427
428/** Set the threshold level of a SilenceDetector,
429Threshold is a -ve number in units of dB/100,
430*/
431#define HPI_SILENCEDETECTOR_THRESHOLD \
432 HPI_CTL_ATTR(SILENCEDETECTOR, 1)
433
434/** get/set the silence time before the detector triggers
435*/
436#define HPI_SILENCEDETECTOR_DELAY \
437 HPI_CTL_ATTR(SILENCEDETECTOR, 3)
438
439/**\}*/
440
441/* Locked memory buffer alloc/free phases */
442/** use one message to allocate or free physical memory */
443#define HPI_BUFFER_CMD_EXTERNAL 0
444/** alloc physical memory */
445#define HPI_BUFFER_CMD_INTERNAL_ALLOC 1
446/** send physical memory address to adapter */
447#define HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER 2
448/** notify adapter to stop using physical buffer */
449#define HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER 3
450/** free physical buffer */
451#define HPI_BUFFER_CMD_INTERNAL_FREE 4
452
453/******************************************* CONTROLX ATTRIBUTES ****/
454/* NOTE: All controlx attributes must be unique, unlike control attributes */
455
456/*****************************************************************************/
457/*****************************************************************************/
458/******** HPI LOW LEVEL MESSAGES *******/
459/*****************************************************************************/
460/*****************************************************************************/
461/** Pnp ids */
462/** "ASI" - actual is "ASX" - need to change */
463#define HPI_ID_ISAPNP_AUDIOSCIENCE 0x0669
464/** PCI vendor ID that AudioScience uses */
465#define HPI_PCI_VENDOR_ID_AUDIOSCIENCE 0x175C
466/** PCI vendor ID that the DSP56301 has */
467#define HPI_PCI_VENDOR_ID_MOTOROLA 0x1057
468/** PCI vendor ID that TI uses */
469#define HPI_PCI_VENDOR_ID_TI 0x104C
470
471#define HPI_PCI_DEV_ID_PCI2040 0xAC60
472/** TI's C6205 PCI interface has this ID */
473#define HPI_PCI_DEV_ID_DSP6205 0xA106
474
475#define HPI_USB_VENDOR_ID_AUDIOSCIENCE 0x1257
476#define HPI_USB_W2K_TAG 0x57495341 /* "ASIW" */
477#define HPI_USB_LINUX_TAG 0x4C495341 /* "ASIL" */
478
479/** First 2 hex digits define the adapter family */
480#define HPI_ADAPTER_FAMILY_MASK 0xff00
481
482#define HPI_ADAPTER_FAMILY_ASI(f) (f & HPI_ADAPTER_FAMILY_MASK)
483#define HPI_ADAPTER_ASI(f) (f)
484
485/******************************************* message types */
486#define HPI_TYPE_MESSAGE 1
487#define HPI_TYPE_RESPONSE 2
488#define HPI_TYPE_DATA 3
489#define HPI_TYPE_SSX2BYPASS_MESSAGE 4
490
491/******************************************* object types */
492#define HPI_OBJ_SUBSYSTEM 1
493#define HPI_OBJ_ADAPTER 2
494#define HPI_OBJ_OSTREAM 3
495#define HPI_OBJ_ISTREAM 4
496#define HPI_OBJ_MIXER 5
497#define HPI_OBJ_NODE 6
498#define HPI_OBJ_CONTROL 7
499#define HPI_OBJ_NVMEMORY 8
500#define HPI_OBJ_GPIO 9
501#define HPI_OBJ_WATCHDOG 10
502#define HPI_OBJ_CLOCK 11
503#define HPI_OBJ_PROFILE 12
504#define HPI_OBJ_CONTROLEX 13
505#define HPI_OBJ_ASYNCEVENT 14
506
507#define HPI_OBJ_MAXINDEX 14
508
509/******************************************* methods/functions */
510
511#define HPI_OBJ_FUNCTION_SPACING 0x100
512#define HPI_MAKE_INDEX(obj, index) (obj * HPI_OBJ_FUNCTION_SPACING + index)
513#define HPI_EXTRACT_INDEX(fn) (fn & 0xff)
514
515/* SUB-SYSTEM */
516#define HPI_SUBSYS_OPEN HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 1)
517#define HPI_SUBSYS_GET_VERSION HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 2)
518#define HPI_SUBSYS_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 3)
519#define HPI_SUBSYS_FIND_ADAPTERS HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 4)
520#define HPI_SUBSYS_CREATE_ADAPTER HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 5)
521#define HPI_SUBSYS_CLOSE HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 6)
522#define HPI_SUBSYS_DELETE_ADAPTER HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 7)
523#define HPI_SUBSYS_DRIVER_LOAD HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 8)
524#define HPI_SUBSYS_DRIVER_UNLOAD HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 9)
525#define HPI_SUBSYS_READ_PORT_8 HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 10)
526#define HPI_SUBSYS_WRITE_PORT_8 HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 11)
527#define HPI_SUBSYS_GET_NUM_ADAPTERS HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 12)
528#define HPI_SUBSYS_GET_ADAPTER HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 13)
529#define HPI_SUBSYS_SET_NETWORK_INTERFACE HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 14)
530#define HPI_SUBSYS_FUNCTION_COUNT 14
531/* ADAPTER */
532#define HPI_ADAPTER_OPEN HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 1)
533#define HPI_ADAPTER_CLOSE HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 2)
534#define HPI_ADAPTER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 3)
535#define HPI_ADAPTER_GET_ASSERT HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 4)
536#define HPI_ADAPTER_TEST_ASSERT HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 5)
537#define HPI_ADAPTER_SET_MODE HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 6)
538#define HPI_ADAPTER_GET_MODE HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 7)
539#define HPI_ADAPTER_ENABLE_CAPABILITY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 8)
540#define HPI_ADAPTER_SELFTEST HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 9)
541#define HPI_ADAPTER_FIND_OBJECT HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 10)
542#define HPI_ADAPTER_QUERY_FLASH HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 11)
543#define HPI_ADAPTER_START_FLASH HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 12)
544#define HPI_ADAPTER_PROGRAM_FLASH HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 13)
545#define HPI_ADAPTER_SET_PROPERTY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 14)
546#define HPI_ADAPTER_GET_PROPERTY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 15)
547#define HPI_ADAPTER_ENUM_PROPERTY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 16)
548#define HPI_ADAPTER_MODULE_INFO HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 17)
549#define HPI_ADAPTER_DEBUG_READ HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 18)
550#define HPI_ADAPTER_FUNCTION_COUNT 18
551/* OUTPUT STREAM */
552#define HPI_OSTREAM_OPEN HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 1)
553#define HPI_OSTREAM_CLOSE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 2)
554#define HPI_OSTREAM_WRITE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 3)
555#define HPI_OSTREAM_START HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 4)
556#define HPI_OSTREAM_STOP HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 5)
557#define HPI_OSTREAM_RESET HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 6)
558#define HPI_OSTREAM_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 7)
559#define HPI_OSTREAM_QUERY_FORMAT HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 8)
560#define HPI_OSTREAM_DATA HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 9)
561#define HPI_OSTREAM_SET_VELOCITY HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 10)
562#define HPI_OSTREAM_SET_PUNCHINOUT HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 11)
563#define HPI_OSTREAM_SINEGEN HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 12)
564#define HPI_OSTREAM_ANC_RESET HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 13)
565#define HPI_OSTREAM_ANC_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 14)
566#define HPI_OSTREAM_ANC_READ HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 15)
567#define HPI_OSTREAM_SET_TIMESCALE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 16)
568#define HPI_OSTREAM_SET_FORMAT HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 17)
569#define HPI_OSTREAM_HOSTBUFFER_ALLOC HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 18)
570#define HPI_OSTREAM_HOSTBUFFER_FREE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 19)
571#define HPI_OSTREAM_GROUP_ADD HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 20)
572#define HPI_OSTREAM_GROUP_GETMAP HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 21)
573#define HPI_OSTREAM_GROUP_RESET HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 22)
574#define HPI_OSTREAM_HOSTBUFFER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 23)
575#define HPI_OSTREAM_WAIT_START HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 24)
576#define HPI_OSTREAM_FUNCTION_COUNT 24
577/* INPUT STREAM */
578#define HPI_ISTREAM_OPEN HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 1)
579#define HPI_ISTREAM_CLOSE HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 2)
580#define HPI_ISTREAM_SET_FORMAT HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 3)
581#define HPI_ISTREAM_READ HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 4)
582#define HPI_ISTREAM_START HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 5)
583#define HPI_ISTREAM_STOP HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 6)
584#define HPI_ISTREAM_RESET HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 7)
585#define HPI_ISTREAM_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 8)
586#define HPI_ISTREAM_QUERY_FORMAT HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 9)
587#define HPI_ISTREAM_ANC_RESET HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 10)
588#define HPI_ISTREAM_ANC_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 11)
589#define HPI_ISTREAM_ANC_WRITE HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 12)
590#define HPI_ISTREAM_HOSTBUFFER_ALLOC HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 13)
591#define HPI_ISTREAM_HOSTBUFFER_FREE HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 14)
592#define HPI_ISTREAM_GROUP_ADD HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 15)
593#define HPI_ISTREAM_GROUP_GETMAP HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 16)
594#define HPI_ISTREAM_GROUP_RESET HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 17)
595#define HPI_ISTREAM_HOSTBUFFER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 18)
596#define HPI_ISTREAM_WAIT_START HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 19)
597#define HPI_ISTREAM_FUNCTION_COUNT 19
598/* MIXER */
599/* NOTE:
600 GET_NODE_INFO, SET_CONNECTION, GET_CONNECTIONS are not currently used */
601#define HPI_MIXER_OPEN HPI_MAKE_INDEX(HPI_OBJ_MIXER, 1)
602#define HPI_MIXER_CLOSE HPI_MAKE_INDEX(HPI_OBJ_MIXER, 2)
603#define HPI_MIXER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_MIXER, 3)
604#define HPI_MIXER_GET_NODE_INFO HPI_MAKE_INDEX(HPI_OBJ_MIXER, 4)
605#define HPI_MIXER_GET_CONTROL HPI_MAKE_INDEX(HPI_OBJ_MIXER, 5)
606#define HPI_MIXER_SET_CONNECTION HPI_MAKE_INDEX(HPI_OBJ_MIXER, 6)
607#define HPI_MIXER_GET_CONNECTIONS HPI_MAKE_INDEX(HPI_OBJ_MIXER, 7)
608#define HPI_MIXER_GET_CONTROL_BY_INDEX HPI_MAKE_INDEX(HPI_OBJ_MIXER, 8)
609#define HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX HPI_MAKE_INDEX(HPI_OBJ_MIXER, 9)
610#define HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES HPI_MAKE_INDEX(HPI_OBJ_MIXER, 10)
611#define HPI_MIXER_STORE HPI_MAKE_INDEX(HPI_OBJ_MIXER, 11)
612#define HPI_MIXER_FUNCTION_COUNT 11
613/* MIXER CONTROLS */
614#define HPI_CONTROL_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 1)
615#define HPI_CONTROL_GET_STATE HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 2)
616#define HPI_CONTROL_SET_STATE HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 3)
617#define HPI_CONTROL_FUNCTION_COUNT 3
618/* NONVOL MEMORY */
619#define HPI_NVMEMORY_OPEN HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 1)
620#define HPI_NVMEMORY_READ_BYTE HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 2)
621#define HPI_NVMEMORY_WRITE_BYTE HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 3)
622#define HPI_NVMEMORY_FUNCTION_COUNT 3
623/* GPIO */
624#define HPI_GPIO_OPEN HPI_MAKE_INDEX(HPI_OBJ_GPIO, 1)
625#define HPI_GPIO_READ_BIT HPI_MAKE_INDEX(HPI_OBJ_GPIO, 2)
626#define HPI_GPIO_WRITE_BIT HPI_MAKE_INDEX(HPI_OBJ_GPIO, 3)
627#define HPI_GPIO_READ_ALL HPI_MAKE_INDEX(HPI_OBJ_GPIO, 4)
628#define HPI_GPIO_WRITE_STATUS HPI_MAKE_INDEX(HPI_OBJ_GPIO, 5)
629#define HPI_GPIO_FUNCTION_COUNT 5
630/* ASYNC EVENT */
631#define HPI_ASYNCEVENT_OPEN HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 1)
632#define HPI_ASYNCEVENT_CLOSE HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 2)
633#define HPI_ASYNCEVENT_WAIT HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 3)
634#define HPI_ASYNCEVENT_GETCOUNT HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 4)
635#define HPI_ASYNCEVENT_GET HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 5)
636#define HPI_ASYNCEVENT_SENDEVENTS HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 6)
637#define HPI_ASYNCEVENT_FUNCTION_COUNT 6
638/* WATCH-DOG */
639#define HPI_WATCHDOG_OPEN HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 1)
640#define HPI_WATCHDOG_SET_TIME HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 2)
641#define HPI_WATCHDOG_PING HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 3)
642/* CLOCK */
643#define HPI_CLOCK_OPEN HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 1)
644#define HPI_CLOCK_SET_TIME HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 2)
645#define HPI_CLOCK_GET_TIME HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 3)
646/* PROFILE */
647#define HPI_PROFILE_OPEN_ALL HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 1)
648#define HPI_PROFILE_START_ALL HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 2)
649#define HPI_PROFILE_STOP_ALL HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 3)
650#define HPI_PROFILE_GET HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 4)
651#define HPI_PROFILE_GET_IDLECOUNT HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 5)
652#define HPI_PROFILE_GET_NAME HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 6)
653#define HPI_PROFILE_GET_UTILIZATION HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 7)
654#define HPI_PROFILE_FUNCTION_COUNT 7
655/* ////////////////////////////////////////////////////////////////////// */
656/* PRIVATE ATTRIBUTES */
657
658/* ////////////////////////////////////////////////////////////////////// */
659/* STRUCTURES */
660#ifndef DISABLE_PRAGMA_PACK1
661#pragma pack(push, 1)
662#endif
663
664/** PCI bus resource */
665struct hpi_pci {
666 u32 __iomem *ap_mem_base[HPI_MAX_ADAPTER_MEM_SPACES];
667 struct pci_dev *p_os_data;
668
669#ifndef HPI64BIT /* keep structure size constant */
670 u32 padding[HPI_MAX_ADAPTER_MEM_SPACES + 1];
671#endif
672 u16 vendor_id;
673 u16 device_id;
674 u16 subsys_vendor_id;
675 u16 subsys_device_id;
676 u16 bus_number;
677 u16 device_number;
678 u32 interrupt;
679};
680
681struct hpi_resource {
682 union {
683 const struct hpi_pci *pci;
684 const char *net_if;
685 } r;
686#ifndef HPI64BIT /* keep structure size constant */
687 u32 pad_to64;
688#endif
689 u16 bus_type; /* HPI_BUS_PNPISA, _PCI, _USB etc */
690 u16 padding;
691
692};
693
694/** Format info used inside struct hpi_message
695 Not the same as public API struct hpi_format */
696struct hpi_msg_format {
697 u32 sample_rate;
698 /**< 11025, 32000, 44100 ... */
699 u32 bit_rate; /**< for MPEG */
700 u32 attributes;
701 /**< Stereo/JointStereo/Mono */
702 u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
703 u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see \ref HPI_FORMATS. */
704};
705
706/** Buffer+format structure.
707 Must be kept 7 * 32 bits to match public struct hpi_datastruct */
708struct hpi_msg_data {
709 struct hpi_msg_format format;
710 u8 *pb_data;
711#ifndef HPI64BIT
712 u32 padding;
713#endif
714 u32 data_size;
715};
716
717/** struct hpi_datastructure used up to 3.04 driver */
718struct hpi_data_legacy32 {
719 struct hpi_format format;
720 u32 pb_data;
721 u32 data_size;
722};
723
724#ifdef HPI64BIT
725/* Compatibility version of struct hpi_data*/
726struct hpi_data_compat32 {
727 struct hpi_msg_format format;
728 u32 pb_data;
729 u32 padding;
730 u32 data_size;
731};
732#endif
733
734struct hpi_buffer {
735 /** placehoder for backward compatability (see dwBufferSize) */
736 struct hpi_msg_format reserved;
737 u32 command; /**< HPI_BUFFER_CMD_xxx*/
738 u32 pci_address; /**< PCI physical address of buffer for DSP DMA */
739 u32 buffer_size; /**< must line up with data_size of HPI_DATA*/
740};
741
742/*/////////////////////////////////////////////////////////////////////////// */
743/* This is used for background buffer bus mastering stream buffers. */
744struct hpi_hostbuffer_status {
745 u32 samples_processed;
746 u32 auxiliary_data_available;
747 u32 stream_state;
748 /* DSP index in to the host bus master buffer. */
749 u32 dSP_index;
750 /* Host index in to the host bus master buffer. */
751 u32 host_index;
752 u32 size_in_bytes;
753};
754
755struct hpi_streamid {
756 u16 object_type;
757 /**< Type of object, HPI_OBJ_OSTREAM or HPI_OBJ_ISTREAM. */
758 u16 stream_index; /**< outstream or instream index. */
759};
760
761struct hpi_punchinout {
762 u32 punch_in_sample;
763 u32 punch_out_sample;
764};
765
766struct hpi_subsys_msg {
767 struct hpi_resource resource;
768};
769
770struct hpi_subsys_res {
771 u32 version;
772 u32 data; /* used to return extended version */
773 u16 num_adapters; /* number of adapters */
774 u16 adapter_index;
775 u16 aw_adapter_list[HPI_MAX_ADAPTERS];
776};
777
778struct hpi_adapter_msg {
779 u32 adapter_mode; /* adapter mode */
780 u16 assert_id; /* assert number for "test assert" call
781 object_index for find object call
782 query_or_set for hpi_adapter_set_mode_ex() */
783 u16 object_type; /* for adapter find object call */
784};
785
786union hpi_adapterx_msg {
787 struct hpi_adapter_msg adapter;
788 struct {
789 u32 offset;
790 } query_flash;
791 struct {
792 u32 offset;
793 u32 length;
794 u32 key;
795 } start_flash;
796 struct {
797 u32 checksum;
798 u16 sequence;
799 u16 length;
800 u16 offset; /**< offset from start of msg to data */
801 u16 unused;
802 } program_flash;
803 struct {
804 u16 property;
805 u16 parameter1;
806 u16 parameter2;
807 } property_set;
808 struct {
809 u16 index;
810 u16 what;
811 u16 property_index;
812 } property_enum;
813 struct {
814 u16 index;
815 } module_info;
816 struct {
817 u32 dsp_address;
818 u32 count_bytes;
819 } debug_read;
820};
821
822struct hpi_adapter_res {
823 u32 serial_number;
824 u16 adapter_type;
825 u16 adapter_index; /* is this needed? also used for dsp_index */
826 u16 num_instreams;
827 u16 num_outstreams;
828 u16 num_mixers;
829 u16 version;
830 u8 sz_adapter_assert[HPI_STRING_LEN];
831};
832
833union hpi_adapterx_res {
834 struct hpi_adapter_res adapter;
835 struct {
836 u32 checksum;
837 u32 length;
838 u32 version;
839 } query_flash;
840 struct {
841 u16 sequence;
842 } program_flash;
843 struct {
844 u16 parameter1;
845 u16 parameter2;
846 } property_get;
847};
848
849struct hpi_stream_msg {
850 union {
851 struct hpi_msg_data data;
852 struct hpi_data_legacy32 data32;
853 u16 velocity;
854 struct hpi_punchinout pio;
855 u32 time_scale;
856 struct hpi_buffer buffer;
857 struct hpi_streamid stream;
858 } u;
859};
860
861struct hpi_stream_res {
862 union {
863 struct {
864 /* size of hardware buffer */
865 u32 buffer_size;
866 /* OutStream - data to play,
867 InStream - data recorded */
868 u32 data_available;
869 /* OutStream - samples played,
870 InStream - samples recorded */
871 u32 samples_transferred;
872 /* Adapter - OutStream - data to play,
873 InStream - data recorded */
874 u32 auxiliary_data_available;
875 u16 state; /* HPI_STATE_PLAYING, _STATE_STOPPED */
876 u16 padding;
877 } stream_info;
878 struct {
879 u32 buffer_size;
880 u32 data_available;
881 u32 samples_transfered;
882 u16 state;
883 u16 outstream_index;
884 u16 instream_index;
885 u16 padding;
886 u32 auxiliary_data_available;
887 } legacy_stream_info;
888 struct {
889 /* bitmap of grouped OutStreams */
890 u32 outstream_group_map;
891 /* bitmap of grouped InStreams */
892 u32 instream_group_map;
893 } group_info;
894 struct {
895 /* pointer to the buffer */
896 u8 *p_buffer;
897 /* pointer to the hostbuffer status */
898 struct hpi_hostbuffer_status *p_status;
899 } hostbuffer_info;
900 } u;
901};
902
903struct hpi_mixer_msg {
904 u16 control_index;
905 u16 control_type; /* = HPI_CONTROL_METER _VOLUME etc */
906 u16 padding1; /* maintain alignment of subsequent fields */
907 u16 node_type1; /* = HPI_SOURCENODE_LINEIN etc */
908 u16 node_index1; /* = 0..N */
909 u16 node_type2;
910 u16 node_index2;
911 u16 padding2; /* round to 4 bytes */
912};
913
914struct hpi_mixer_res {
915 u16 src_node_type; /* = HPI_SOURCENODE_LINEIN etc */
916 u16 src_node_index; /* = 0..N */
917 u16 dst_node_type;
918 u16 dst_node_index;
919 /* Also controlType for MixerGetControlByIndex */
920 u16 control_index;
921 /* may indicate which DSP the control is located on */
922 u16 dsp_index;
923};
924
925union hpi_mixerx_msg {
926 struct {
927 u16 starting_index;
928 u16 flags;
929 u32 length_in_bytes; /* length in bytes of p_data */
930 u32 p_data; /* pointer to a data array */
931 } gcabi;
932 struct {
933 u16 command;
934 u16 index;
935 } store; /* for HPI_MIXER_STORE message */
936};
937
938union hpi_mixerx_res {
939 struct {
940 u32 bytes_returned; /* size of items returned */
941 u32 p_data; /* pointer to data array */
942 u16 more_to_do; /* indicates if there is more to do */
943 } gcabi;
944};
945
946struct hpi_control_msg {
947 u16 attribute; /* control attribute or property */
948 u16 saved_index;
949 u32 param1; /* generic parameter 1 */
950 u32 param2; /* generic parameter 2 */
951 short an_log_value[HPI_MAX_CHANNELS];
952};
953
954struct hpi_control_union_msg {
955 u16 attribute; /* control attribute or property */
956 u16 saved_index; /* only used in ctrl save/restore */
957 union {
958 struct {
959 u32 param1; /* generic parameter 1 */
960 u32 param2; /* generic parameter 2 */
961 short an_log_value[HPI_MAX_CHANNELS];
962 } old;
963 union {
964 u32 frequency;
965 u32 gain;
966 u32 band;
967 u32 deemphasis;
968 u32 program;
969 struct {
970 u32 mode;
971 u32 value;
972 } mode;
973 } tuner;
974 } u;
975};
976
977struct hpi_control_res {
978 /* Could make union. dwParam, anLogValue never used in same response */
979 u32 param1;
980 u32 param2;
981 short an_log_value[HPI_MAX_CHANNELS];
982};
983
984union hpi_control_union_res {
985 struct {
986 u32 param1;
987 u32 param2;
988 short an_log_value[HPI_MAX_CHANNELS];
989 } old;
990 union {
991 u32 band;
992 u32 frequency;
993 u32 gain;
994 u32 level;
995 u32 deemphasis;
996 struct {
997 u32 data[2];
998 u32 bLER;
999 } rds;
1000 } tuner;
1001 struct {
1002 char sz_data[8];
1003 u32 remaining_chars;
1004 } chars8;
1005 char c_data12[12];
1006};
1007
1008/* HPI_CONTROLX_STRUCTURES */
1009
1010/* Message */
1011
1012/** Used for all HMI variables where max length <= 8 bytes
1013*/
1014struct hpi_controlx_msg_cobranet_data {
1015 u32 hmi_address;
1016 u32 byte_count;
1017 u32 data[2];
1018};
1019
1020/** Used for string data, and for packet bridge
1021*/
1022struct hpi_controlx_msg_cobranet_bigdata {
1023 u32 hmi_address;
1024 u32 byte_count;
1025 u8 *pb_data;
1026#ifndef HPI64BIT
1027 u32 padding;
1028#endif
1029};
1030
1031/** Used for PADS control reading of string fields.
1032*/
1033struct hpi_controlx_msg_pad_data {
1034 u32 field;
1035 u32 byte_count;
1036 u8 *pb_data;
1037#ifndef HPI64BIT
1038 u32 padding;
1039#endif
1040};
1041
1042/** Used for generic data
1043*/
1044
1045struct hpi_controlx_msg_generic {
1046 u32 param1;
1047 u32 param2;
1048};
1049
1050struct hpi_controlx_msg {
1051 u16 attribute; /* control attribute or property */
1052 u16 saved_index;
1053 union {
1054 struct hpi_controlx_msg_cobranet_data cobranet_data;
1055 struct hpi_controlx_msg_cobranet_bigdata cobranet_bigdata;
1056 struct hpi_controlx_msg_generic generic;
1057 struct hpi_controlx_msg_pad_data pad_data;
1058 /*struct param_value universal_value; */
1059 /* nothing extra to send for status read */
1060 } u;
1061};
1062
1063/* Response */
1064/**
1065*/
1066struct hpi_controlx_res_cobranet_data {
1067 u32 byte_count;
1068 u32 data[2];
1069};
1070
1071struct hpi_controlx_res_cobranet_bigdata {
1072 u32 byte_count;
1073};
1074
1075struct hpi_controlx_res_cobranet_status {
1076 u32 status;
1077 u32 readable_size;
1078 u32 writeable_size;
1079};
1080
1081struct hpi_controlx_res_generic {
1082 u32 param1;
1083 u32 param2;
1084};
1085
1086struct hpi_controlx_res {
1087 union {
1088 struct hpi_controlx_res_cobranet_bigdata cobranet_bigdata;
1089 struct hpi_controlx_res_cobranet_data cobranet_data;
1090 struct hpi_controlx_res_cobranet_status cobranet_status;
1091 struct hpi_controlx_res_generic generic;
1092 /*struct param_info universal_info; */
1093 /*struct param_value universal_value; */
1094 } u;
1095};
1096
1097struct hpi_nvmemory_msg {
1098 u16 address;
1099 u16 data;
1100};
1101
1102struct hpi_nvmemory_res {
1103 u16 size_in_bytes;
1104 u16 data;
1105};
1106
1107struct hpi_gpio_msg {
1108 u16 bit_index;
1109 u16 bit_data;
1110};
1111
1112struct hpi_gpio_res {
1113 u16 number_input_bits;
1114 u16 number_output_bits;
1115 u16 bit_data[4];
1116};
1117
1118struct hpi_async_msg {
1119 u32 events;
1120 u16 maximum_events;
1121 u16 padding;
1122};
1123
1124struct hpi_async_res {
1125 union {
1126 struct {
1127 u16 count;
1128 } count;
1129 struct {
1130 u32 events;
1131 u16 number_returned;
1132 u16 padding;
1133 } get;
1134 struct hpi_async_event event;
1135 } u;
1136};
1137
1138struct hpi_watchdog_msg {
1139 u32 time_ms;
1140};
1141
1142struct hpi_watchdog_res {
1143 u32 time_ms;
1144};
1145
1146struct hpi_clock_msg {
1147 u16 hours;
1148 u16 minutes;
1149 u16 seconds;
1150 u16 milli_seconds;
1151};
1152
1153struct hpi_clock_res {
1154 u16 size_in_bytes;
1155 u16 hours;
1156 u16 minutes;
1157 u16 seconds;
1158 u16 milli_seconds;
1159 u16 padding;
1160};
1161
1162struct hpi_profile_msg {
1163 u16 bin_index;
1164 u16 padding;
1165};
1166
1167struct hpi_profile_res_open {
1168 u16 max_profiles;
1169};
1170
1171struct hpi_profile_res_time {
1172 u32 micro_seconds;
1173 u32 call_count;
1174 u32 max_micro_seconds;
1175 u32 min_micro_seconds;
1176 u16 seconds;
1177};
1178
1179struct hpi_profile_res_name {
1180 u8 sz_name[32];
1181};
1182
1183struct hpi_profile_res {
1184 union {
1185 struct hpi_profile_res_open o;
1186 struct hpi_profile_res_time t;
1187 struct hpi_profile_res_name n;
1188 } u;
1189};
1190
1191struct hpi_message_header {
1192 u16 size; /* total size in bytes */
1193 u8 type; /* HPI_TYPE_MESSAGE */
1194 u8 version; /* message version */
1195 u16 object; /* HPI_OBJ_* */
1196 u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
1197 u16 adapter_index; /* the adapter index */
1198 u16 obj_index; /* */
1199};
1200
1201struct hpi_message {
1202 /* following fields must match HPI_MESSAGE_HEADER */
1203 u16 size; /* total size in bytes */
1204 u8 type; /* HPI_TYPE_MESSAGE */
1205 u8 version; /* message version */
1206 u16 object; /* HPI_OBJ_* */
1207 u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
1208 u16 adapter_index; /* the adapter index */
1209 u16 obj_index; /* */
1210 union {
1211 struct hpi_subsys_msg s;
1212 struct hpi_adapter_msg a;
1213 union hpi_adapterx_msg ax;
1214 struct hpi_stream_msg d;
1215 struct hpi_mixer_msg m;
1216 union hpi_mixerx_msg mx; /* extended mixer; */
1217 struct hpi_control_msg c; /* mixer control; */
1218 /* identical to struct hpi_control_msg,
1219 but field naming is improved */
1220 struct hpi_control_union_msg cu;
1221 struct hpi_controlx_msg cx; /* extended mixer control; */
1222 struct hpi_nvmemory_msg n;
1223 struct hpi_gpio_msg l; /* digital i/o */
1224 struct hpi_watchdog_msg w;
1225 struct hpi_clock_msg t; /* dsp time */
1226 struct hpi_profile_msg p;
1227 struct hpi_async_msg as;
1228 char fixed_size[32];
1229 } u;
1230};
1231
1232#define HPI_MESSAGE_SIZE_BY_OBJECT { \
1233 sizeof(struct hpi_message_header) , /* default, no object type 0 */ \
1234 sizeof(struct hpi_message_header) + sizeof(struct hpi_subsys_msg),\
1235 sizeof(struct hpi_message_header) + sizeof(union hpi_adapterx_msg),\
1236 sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\
1237 sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\
1238 sizeof(struct hpi_message_header) + sizeof(struct hpi_mixer_msg),\
1239 sizeof(struct hpi_message_header) , /* no node message */ \
1240 sizeof(struct hpi_message_header) + sizeof(struct hpi_control_msg),\
1241 sizeof(struct hpi_message_header) + sizeof(struct hpi_nvmemory_msg),\
1242 sizeof(struct hpi_message_header) + sizeof(struct hpi_gpio_msg),\
1243 sizeof(struct hpi_message_header) + sizeof(struct hpi_watchdog_msg),\
1244 sizeof(struct hpi_message_header) + sizeof(struct hpi_clock_msg),\
1245 sizeof(struct hpi_message_header) + sizeof(struct hpi_profile_msg),\
1246 sizeof(struct hpi_message_header) + sizeof(struct hpi_controlx_msg),\
1247 sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \
1248}
1249
1250struct hpi_response_header {
1251 u16 size;
1252 u8 type; /* HPI_TYPE_RESPONSE */
1253 u8 version; /* response version */
1254 u16 object; /* HPI_OBJ_* */
1255 u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
1256 u16 error; /* HPI_ERROR_xxx */
1257 u16 specific_error; /* adapter specific error */
1258};
1259
1260struct hpi_response {
1261/* following fields must match HPI_RESPONSE_HEADER */
1262 u16 size;
1263 u8 type; /* HPI_TYPE_RESPONSE */
1264 u8 version; /* response version */
1265 u16 object; /* HPI_OBJ_* */
1266 u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */
1267 u16 error; /* HPI_ERROR_xxx */
1268 u16 specific_error; /* adapter specific error */
1269 union {
1270 struct hpi_subsys_res s;
1271 struct hpi_adapter_res a;
1272 union hpi_adapterx_res ax;
1273 struct hpi_stream_res d;
1274 struct hpi_mixer_res m;
1275 union hpi_mixerx_res mx; /* extended mixer; */
1276 struct hpi_control_res c; /* mixer control; */
1277 /* identical to hpi_control_res, but field naming is improved */
1278 union hpi_control_union_res cu;
1279 struct hpi_controlx_res cx; /* extended mixer control; */
1280 struct hpi_nvmemory_res n;
1281 struct hpi_gpio_res l; /* digital i/o */
1282 struct hpi_watchdog_res w;
1283 struct hpi_clock_res t; /* dsp time */
1284 struct hpi_profile_res p;
1285 struct hpi_async_res as;
1286 u8 bytes[52];
1287 } u;
1288};
1289
1290#define HPI_RESPONSE_SIZE_BY_OBJECT { \
1291 sizeof(struct hpi_response_header) ,/* default, no object type 0 */ \
1292 sizeof(struct hpi_response_header) + sizeof(struct hpi_subsys_res),\
1293 sizeof(struct hpi_response_header) + sizeof(union hpi_adapterx_res),\
1294 sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\
1295 sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\
1296 sizeof(struct hpi_response_header) + sizeof(struct hpi_mixer_res),\
1297 sizeof(struct hpi_response_header) , /* no node response */ \
1298 sizeof(struct hpi_response_header) + sizeof(struct hpi_control_res),\
1299 sizeof(struct hpi_response_header) + sizeof(struct hpi_nvmemory_res),\
1300 sizeof(struct hpi_response_header) + sizeof(struct hpi_gpio_res),\
1301 sizeof(struct hpi_response_header) + sizeof(struct hpi_watchdog_res),\
1302 sizeof(struct hpi_response_header) + sizeof(struct hpi_clock_res),\
1303 sizeof(struct hpi_response_header) + sizeof(struct hpi_profile_res),\
1304 sizeof(struct hpi_response_header) + sizeof(struct hpi_controlx_res),\
1305 sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \
1306}
1307
1308/*********************** version 1 message/response *****************************/
1309#define HPINET_ETHERNET_DATA_SIZE (1500)
1310#define HPINET_IP_HDR_SIZE (20)
1311#define HPINET_IP_DATA_SIZE (HPINET_ETHERNET_DATA_SIZE - HPINET_IP_HDR_SIZE)
1312#define HPINET_UDP_HDR_SIZE (8)
1313#define HPINET_UDP_DATA_SIZE (HPINET_IP_DATA_SIZE - HPINET_UDP_HDR_SIZE)
1314#define HPINET_ASI_HDR_SIZE (2)
1315#define HPINET_ASI_DATA_SIZE (HPINET_UDP_DATA_SIZE - HPINET_ASI_HDR_SIZE)
1316
1317#define HPI_MAX_PAYLOAD_SIZE (HPINET_ASI_DATA_SIZE - 2)
1318
1319/* New style message/response, but still V0 compatible */
1320struct hpi_msg_adapter_get_info {
1321 struct hpi_message_header h;
1322};
1323
1324struct hpi_res_adapter_get_info {
1325 struct hpi_response_header h; /*v0 */
1326 struct hpi_adapter_res p;
1327};
1328
1329/* padding is so these are same size as v0 hpi_message */
1330struct hpi_msg_adapter_query_flash {
1331 struct hpi_message_header h;
1332 u32 offset;
1333 u8 pad_to_version0_size[sizeof(struct hpi_message) - /* V0 res */
1334 sizeof(struct hpi_message_header) - 1 * sizeof(u32)];
1335};
1336
1337/* padding is so these are same size as v0 hpi_response */
1338struct hpi_res_adapter_query_flash {
1339 struct hpi_response_header h;
1340 u32 checksum;
1341 u32 length;
1342 u32 version;
1343 u8 pad_to_version0_size[sizeof(struct hpi_response) - /* V0 res */
1344 sizeof(struct hpi_response_header) - 3 * sizeof(u32)];
1345};
1346
1347struct hpi_msg_adapter_start_flash {
1348 struct hpi_message_header h;
1349 u32 offset;
1350 u32 length;
1351 u32 key;
1352 u8 pad_to_version0_size[sizeof(struct hpi_message) - /* V0 res */
1353 sizeof(struct hpi_message_header) - 3 * sizeof(u32)];
1354};
1355
1356struct hpi_res_adapter_start_flash {
1357 struct hpi_response_header h;
1358 u8 pad_to_version0_size[sizeof(struct hpi_response) - /* V0 res */
1359 sizeof(struct hpi_response_header)];
1360};
1361
1362struct hpi_msg_adapter_program_flash_payload {
1363 u32 checksum;
1364 u16 sequence;
1365 u16 length;
1366 u16 offset; /**< offset from start of msg to data */
1367 u16 unused;
1368 /* ensure sizeof(header + payload) == sizeof(hpi_message_V0)
1369 because old firmware expects data after message of this size */
1370 u8 pad_to_version0_size[sizeof(struct hpi_message) - /* V0 message */
1371 sizeof(struct hpi_message_header) - sizeof(u32) -
1372 4 * sizeof(u16)];
1373};
1374
1375struct hpi_msg_adapter_program_flash {
1376 struct hpi_message_header h;
1377 struct hpi_msg_adapter_program_flash_payload p;
1378 u32 data[256];
1379};
1380
1381struct hpi_res_adapter_program_flash {
1382 struct hpi_response_header h;
1383 u16 sequence;
1384 u8 pad_to_version0_size[sizeof(struct hpi_response) - /* V0 res */
1385 sizeof(struct hpi_response_header) - sizeof(u16)];
1386};
1387
1388#if 1
1389#define hpi_message_header_v1 hpi_message_header
1390#define hpi_response_header_v1 hpi_response_header
1391#else
1392/* V1 headers in Addition to v0 headers */
1393struct hpi_message_header_v1 {
1394 struct hpi_message_header h0;
1395/* struct {
1396} h1; */
1397};
1398
1399struct hpi_response_header_v1 {
1400 struct hpi_response_header h0;
1401 struct {
1402 u16 adapter_index; /* the adapter index */
1403 u16 obj_index; /* object index */
1404 } h1;
1405};
1406#endif
1407
1408/* STRV HPI Packet */
1409struct hpi_msg_strv {
1410 struct hpi_message_header h;
1411 struct hpi_entity strv;
1412};
1413
1414struct hpi_res_strv {
1415 struct hpi_response_header h;
1416 struct hpi_entity strv;
1417};
1418#define MIN_STRV_PACKET_SIZE sizeof(struct hpi_res_strv)
1419
1420struct hpi_msg_payload_v0 {
1421 struct hpi_message_header h;
1422 union {
1423 struct hpi_subsys_msg s;
1424 struct hpi_adapter_msg a;
1425 union hpi_adapterx_msg ax;
1426 struct hpi_stream_msg d;
1427 struct hpi_mixer_msg m;
1428 union hpi_mixerx_msg mx;
1429 struct hpi_control_msg c;
1430 struct hpi_control_union_msg cu;
1431 struct hpi_controlx_msg cx;
1432 struct hpi_nvmemory_msg n;
1433 struct hpi_gpio_msg l;
1434 struct hpi_watchdog_msg w;
1435 struct hpi_clock_msg t;
1436 struct hpi_profile_msg p;
1437 struct hpi_async_msg as;
1438 } u;
1439};
1440
1441struct hpi_res_payload_v0 {
1442 struct hpi_response_header h;
1443 union {
1444 struct hpi_subsys_res s;
1445 struct hpi_adapter_res a;
1446 union hpi_adapterx_res ax;
1447 struct hpi_stream_res d;
1448 struct hpi_mixer_res m;
1449 union hpi_mixerx_res mx;
1450 struct hpi_control_res c;
1451 union hpi_control_union_res cu;
1452 struct hpi_controlx_res cx;
1453 struct hpi_nvmemory_res n;
1454 struct hpi_gpio_res l;
1455 struct hpi_watchdog_res w;
1456 struct hpi_clock_res t;
1457 struct hpi_profile_res p;
1458 struct hpi_async_res as;
1459 } u;
1460};
1461
1462union hpi_message_buffer_v1 {
1463 struct hpi_message m0; /* version 0 */
1464 struct hpi_message_header_v1 h;
1465 unsigned char buf[HPI_MAX_PAYLOAD_SIZE];
1466};
1467
1468union hpi_response_buffer_v1 {
1469 struct hpi_response r0; /* version 0 */
1470 struct hpi_response_header_v1 h;
1471 unsigned char buf[HPI_MAX_PAYLOAD_SIZE];
1472};
1473
1474compile_time_assert((sizeof(union hpi_message_buffer_v1) <=
1475 HPI_MAX_PAYLOAD_SIZE), message_buffer_ok);
1476compile_time_assert((sizeof(union hpi_response_buffer_v1) <=
1477 HPI_MAX_PAYLOAD_SIZE), response_buffer_ok);
1478
1479/*////////////////////////////////////////////////////////////////////////// */
1480/* declarations for compact control calls */
1481struct hpi_control_defn {
1482 u8 type;
1483 u8 channels;
1484 u8 src_node_type;
1485 u8 src_node_index;
1486 u8 dest_node_type;
1487 u8 dest_node_index;
1488};
1489
1490/*////////////////////////////////////////////////////////////////////////// */
1491/* declarations for control caching (internal to HPI<->DSP interaction) */
1492
1493/** A compact representation of (part of) a controls state.
1494Used for efficient transfer of the control state
1495between DSP and host or across a network
1496*/
1497struct hpi_control_cache_info {
1498 /** one of HPI_CONTROL_* */
1499 u8 control_type;
1500 /** The total size of cached information in 32-bit words. */
1501 u8 size_in32bit_words;
1502 /** The original index of the control on the DSP */
1503 u16 control_index;
1504};
1505
1506struct hpi_control_cache_single {
1507 struct hpi_control_cache_info i;
1508 union {
1509 struct { /* volume */
1510 u16 an_log[2];
1511 } v;
1512 struct { /* peak meter */
1513 u16 an_log_peak[2];
1514 u16 an_logRMS[2];
1515 } p;
1516 struct { /* channel mode */
1517 u16 mode;
1518 } m;
1519 struct { /* multiplexer */
1520 u16 source_node_type;
1521 u16 source_node_index;
1522 } x;
1523 struct { /* level/trim */
1524 u16 an_log[2];
1525 } l;
1526 struct { /* tuner - partial caching.
1527 some attributes go to the DSP. */
1528 u32 freq_ink_hz;
1529 u16 band;
1530 u16 level;
1531 } t;
1532 struct { /* AESEBU rx status */
1533 u32 error_status;
1534 u32 source;
1535 } aes3rx;
1536 struct { /* AESEBU tx */
1537 u32 format;
1538 } aes3tx;
1539 struct { /* tone detector */
1540 u16 state;
1541 } tone;
1542 struct { /* silence detector */
1543 u32 state;
1544 u32 count;
1545 } silence;
1546 struct { /* sample clock */
1547 u16 source;
1548 u16 source_index;
1549 u32 sample_rate;
1550 } clk;
1551 struct { /* microphone control */
1552 u16 state;
1553 } phantom_power;
1554 struct { /* generic control */
1555 u32 dw1;
1556 u32 dw2;
1557 } g;
1558 } u;
1559};
1560
1561struct hpi_control_cache_pad {
1562 struct hpi_control_cache_info i;
1563 u32 field_valid_flags;
1564 u8 c_channel[8];
1565 u8 c_artist[40];
1566 u8 c_title[40];
1567 u8 c_comment[200];
1568 u32 pTY;
1569 u32 pI;
1570 u32 traffic_supported;
1571 u32 traffic_anouncement;
1572};
1573
1574/*/////////////////////////////////////////////////////////////////////////// */
1575/* declarations for 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */
1576struct hpi_fifo_buffer {
1577 u32 size;
1578 u32 dSP_index;
1579 u32 host_index;
1580};
1581
1582#ifndef DISABLE_PRAGMA_PACK1
1583#pragma pack(pop)
1584#endif
1585
1586/* skip host side function declarations for DSP
1587 compile and documentation extraction */
1588
1589char hpi_handle_object(const u32 handle);
1590
1591void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index,
1592 u16 *pw_object_index);
1593
1594u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index,
1595 const u16 object_index);
1596
1597/*////////////////////////////////////////////////////////////////////////// */
1598
1599/* main HPI entry point */
1600hpi_handler_func hpi_send_recv;
1601
1602/* UDP message */
1603void hpi_send_recvUDP(struct hpi_message *phm, struct hpi_response *phr,
1604 const unsigned int timeout);
1605
1606/* used in PnP OS/driver */
1607u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys,
1608 const struct hpi_resource *p_resource, u16 *pw_adapter_index);
1609
1610u16 hpi_subsys_delete_adapter(const struct hpi_hsubsys *ph_subsys,
1611 u16 adapter_index);
1612
1613u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
1614 u32 h_outstream, u8 **pp_buffer,
1615 struct hpi_hostbuffer_status **pp_status);
1616
1617u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
1618 u32 h_instream, u8 **pp_buffer,
1619 struct hpi_hostbuffer_status **pp_status);
1620
1621u16 hpi_adapter_restart(u16 adapter_index);
1622
1623/*
1624The following 3 functions were last declared in header files for
1625driver 3.10. HPI_ControlQuery() used to be the recommended way
1626of getting a volume range. Declared here for binary asihpi32.dll
1627compatibility.
1628*/
1629
1630void hpi_format_to_msg(struct hpi_msg_format *pMF,
1631 const struct hpi_format *pF);
1632void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR);
1633
1634/*////////////////////////////////////////////////////////////////////////// */
1635/* declarations for individual HPI entry points */
1636hpi_handler_func HPI_1000;
1637hpi_handler_func HPI_6000;
1638hpi_handler_func HPI_6205;
1639hpi_handler_func HPI_COMMON;
1640
1641#endif /* _HPI_INTERNAL_H_ */
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
new file mode 100644
index 000000000000..565102cae4f8
--- /dev/null
+++ b/sound/pci/asihpi/hpicmn.c
@@ -0,0 +1,643 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19\file hpicmn.c
20
21 Common functions used by hpixxxx.c modules
22
23(C) Copyright AudioScience Inc. 1998-2003
24*******************************************************************************/
25#define SOURCEFILE_NAME "hpicmn.c"
26
27#include "hpi_internal.h"
28#include "hpidebug.h"
29#include "hpicmn.h"
30
31struct hpi_adapters_list {
32 struct hpios_spinlock list_lock;
33 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
34 u16 gw_num_adapters;
35};
36
37static struct hpi_adapters_list adapters;
38
39/**
40* Given an HPI Message that was sent out and a response that was received,
41* validate that the response has the correct fields filled in,
42* i.e ObjectType, Function etc
43**/
44u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
45{
46 u16 error = 0;
47
48 if ((phr->type != HPI_TYPE_RESPONSE)
49 || (phr->object != phm->object)
50 || (phr->function != phm->function))
51 error = HPI_ERROR_INVALID_RESPONSE;
52
53 return error;
54}
55
56u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
57{
58 u16 retval = 0;
59 /*HPI_ASSERT(pao->wAdapterType); */
60
61 hpios_alistlock_lock(&adapters);
62
63 if (pao->index >= HPI_MAX_ADAPTERS) {
64 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
65 goto unlock;
66 }
67
68 if (adapters.adapter[pao->index].adapter_type) {
69 {
70 retval = HPI_DUPLICATE_ADAPTER_NUMBER;
71 goto unlock;
72 }
73 }
74 adapters.adapter[pao->index] = *pao;
75 hpios_dsplock_init(&adapters.adapter[pao->index]);
76 adapters.gw_num_adapters++;
77
78unlock:
79 hpios_alistlock_un_lock(&adapters);
80 return retval;
81}
82
83void hpi_delete_adapter(struct hpi_adapter_obj *pao)
84{
85 memset(pao, 0, sizeof(struct hpi_adapter_obj));
86
87 hpios_alistlock_lock(&adapters);
88 adapters.gw_num_adapters--; /* dec the number of adapters */
89 hpios_alistlock_un_lock(&adapters);
90}
91
92/**
93* FindAdapter returns a pointer to the struct hpi_adapter_obj with
94* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
95*
96*/
97struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
98{
99 struct hpi_adapter_obj *pao = NULL;
100
101 if (adapter_index >= HPI_MAX_ADAPTERS) {
102 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
103 adapter_index);
104 return NULL;
105 }
106
107 pao = &adapters.adapter[adapter_index];
108 if (pao->adapter_type != 0) {
109 /*
110 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
111 wAdapterIndex);
112 */
113 return pao;
114 } else {
115 /*
116 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
117 wAdapterIndex);
118 */
119 return NULL;
120 }
121}
122
123/**
124*
125* wipe an HPI_ADAPTERS_LIST structure.
126*
127**/
128static void wipe_adapter_list(void
129 )
130{
131 memset(&adapters, 0, sizeof(adapters));
132}
133
134/**
135* SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
136* with all adapters in the given HPI_ADAPTERS_LIST.
137*
138*/
139static void subsys_get_adapters(struct hpi_response *phr)
140{
141 /* fill in the response adapter array with the position */
142 /* identified by the adapter number/index of the adapters in */
143 /* this HPI */
144 /* i.e. if we have an A120 with it's jumper set to */
145 /* Adapter Number 2 then put an Adapter type A120 in the */
146 /* array in position 1 */
147 /* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */
148
149 /* input: NONE */
150 /* output: wNumAdapters */
151 /* awAdapter[] */
152 /* */
153
154 short i;
155 struct hpi_adapter_obj *pao = NULL;
156
157 HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n");
158
159 /* for each adapter, place it's type in the position of the array */
160 /* corresponding to it's adapter number */
161 for (i = 0; i < adapters.gw_num_adapters; i++) {
162 pao = &adapters.adapter[i];
163 if (phr->u.s.aw_adapter_list[pao->index] != 0) {
164 phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
165 phr->specific_error = pao->index;
166 return;
167 }
168 phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
169 }
170
171 phr->u.s.num_adapters = adapters.gw_num_adapters;
172 phr->error = 0; /* the function completed OK; */
173}
174
175static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
176{
177 unsigned int i;
178 int cached = 0;
179 if (!pC)
180 return 0;
181 if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
182 && (pC->cache_size_in_bytes)
183 ) {
184 u32 *p_master_cache;
185 pC->init = 1;
186
187 p_master_cache = (u32 *)pC->p_cache;
188 HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
189 pC->control_count);
190 for (i = 0; i < pC->control_count; i++) {
191 struct hpi_control_cache_info *info =
192 (struct hpi_control_cache_info *)
193 p_master_cache;
194
195 if (info->control_type) {
196 pC->p_info[i] = info;
197 cached++;
198 } else
199 pC->p_info[i] = NULL;
200
201 if (info->size_in32bit_words)
202 p_master_cache += info->size_in32bit_words;
203 else
204 p_master_cache +=
205 sizeof(struct
206 hpi_control_cache_single) /
207 sizeof(u32);
208
209 HPI_DEBUG_LOG(VERBOSE,
210 "cached %d, pinfo %p index %d type %d\n",
211 cached, pC->p_info[i], info->control_index,
212 info->control_type);
213 }
214 /*
215 We didn't find anything to cache, so try again later !
216 */
217 if (!cached)
218 pC->init = 0;
219 }
220 return pC->init;
221}
222
223/** Find a control.
224*/
225static short find_control(struct hpi_message *phm,
226 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
227 u16 *pw_control_index)
228{
229 *pw_control_index = phm->obj_index;
230
231 if (!control_cache_alloc_check(p_cache)) {
232 HPI_DEBUG_LOG(VERBOSE,
233 "control_cache_alloc_check() failed. adap%d ci%d\n",
234 phm->adapter_index, *pw_control_index);
235 return 0;
236 }
237
238 *pI = p_cache->p_info[*pw_control_index];
239 if (!*pI) {
240 HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
241 phm->adapter_index, *pw_control_index);
242 return 0;
243 } else {
244 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
245 (*pI)->control_type);
246 }
247 return 1;
248}
249
250/** Used by the kernel driver to figure out if a buffer needs mapping.
251 */
252short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
253 struct hpi_message *phm, void **p, unsigned int *pN)
254{
255 *pN = 0;
256 *p = NULL;
257 if ((phm->function == HPI_CONTROL_GET_STATE)
258 && (phm->object == HPI_OBJ_CONTROLEX)
259 ) {
260 u16 control_index;
261 struct hpi_control_cache_info *pI;
262
263 if (!find_control(phm, p_cache, &pI, &control_index))
264 return 0;
265 }
266 return 0;
267}
268
269/* allow unified treatment of several string fields within struct */
270#define HPICMN_PAD_OFS_AND_SIZE(m) {\
271 offsetof(struct hpi_control_cache_pad, m), \
272 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
273
274struct pad_ofs_size {
275 unsigned int offset;
276 unsigned int field_size;
277};
278
279static struct pad_ofs_size pad_desc[] = {
280 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
281 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
282 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
283 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
284};
285
286/** CheckControlCache checks the cache and fills the struct hpi_response
287 * accordingly. It returns one if a cache hit occurred, zero otherwise.
288 */
289short hpi_check_control_cache(struct hpi_control_cache *p_cache,
290 struct hpi_message *phm, struct hpi_response *phr)
291{
292 short found = 1;
293 u16 control_index;
294 struct hpi_control_cache_info *pI;
295 struct hpi_control_cache_single *pC;
296 struct hpi_control_cache_pad *p_pad;
297
298 if (!find_control(phm, p_cache, &pI, &control_index))
299 return 0;
300
301 phr->error = 0;
302
303 /* pC is the default cached control strucure. May be cast to
304 something else in the following switch statement.
305 */
306 pC = (struct hpi_control_cache_single *)pI;
307 p_pad = (struct hpi_control_cache_pad *)pI;
308
309 switch (pI->control_type) {
310
311 case HPI_CONTROL_METER:
312 if (phm->u.c.attribute == HPI_METER_PEAK) {
313 phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0];
314 phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1];
315 } else if (phm->u.c.attribute == HPI_METER_RMS) {
316 phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0];
317 phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1];
318 } else
319 found = 0;
320 break;
321 case HPI_CONTROL_VOLUME:
322 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
323 phr->u.c.an_log_value[0] = pC->u.v.an_log[0];
324 phr->u.c.an_log_value[1] = pC->u.v.an_log[1];
325 } else
326 found = 0;
327 break;
328 case HPI_CONTROL_MULTIPLEXER:
329 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
330 phr->u.c.param1 = pC->u.x.source_node_type;
331 phr->u.c.param2 = pC->u.x.source_node_index;
332 } else {
333 found = 0;
334 }
335 break;
336 case HPI_CONTROL_CHANNEL_MODE:
337 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
338 phr->u.c.param1 = pC->u.m.mode;
339 else
340 found = 0;
341 break;
342 case HPI_CONTROL_LEVEL:
343 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
344 phr->u.c.an_log_value[0] = pC->u.l.an_log[0];
345 phr->u.c.an_log_value[1] = pC->u.l.an_log[1];
346 } else
347 found = 0;
348 break;
349 case HPI_CONTROL_TUNER:
350 {
351 struct hpi_control_cache_single *pCT =
352 (struct hpi_control_cache_single *)pI;
353 if (phm->u.c.attribute == HPI_TUNER_FREQ)
354 phr->u.c.param1 = pCT->u.t.freq_ink_hz;
355 else if (phm->u.c.attribute == HPI_TUNER_BAND)
356 phr->u.c.param1 = pCT->u.t.band;
357 else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
358 && (phm->u.c.param1 ==
359 HPI_TUNER_LEVEL_AVERAGE))
360 phr->u.c.param1 = pCT->u.t.level;
361 else
362 found = 0;
363 }
364 break;
365 case HPI_CONTROL_AESEBU_RECEIVER:
366 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
367 phr->u.c.param1 = pC->u.aes3rx.error_status;
368 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
369 phr->u.c.param1 = pC->u.aes3rx.source;
370 else
371 found = 0;
372 break;
373 case HPI_CONTROL_AESEBU_TRANSMITTER:
374 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
375 phr->u.c.param1 = pC->u.aes3tx.format;
376 else
377 found = 0;
378 break;
379 case HPI_CONTROL_TONEDETECTOR:
380 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
381 phr->u.c.param1 = pC->u.tone.state;
382 else
383 found = 0;
384 break;
385 case HPI_CONTROL_SILENCEDETECTOR:
386 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
387 phr->u.c.param1 = pC->u.silence.state;
388 phr->u.c.param2 = pC->u.silence.count;
389 } else
390 found = 0;
391 break;
392 case HPI_CONTROL_MICROPHONE:
393 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
394 phr->u.c.param1 = pC->u.phantom_power.state;
395 else
396 found = 0;
397 break;
398 case HPI_CONTROL_SAMPLECLOCK:
399 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
400 phr->u.c.param1 = pC->u.clk.source;
401 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
402 if (pC->u.clk.source_index ==
403 HPI_ERROR_ILLEGAL_CACHE_VALUE) {
404 phr->u.c.param1 = 0;
405 phr->error = HPI_ERROR_INVALID_OPERATION;
406 } else
407 phr->u.c.param1 = pC->u.clk.source_index;
408 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
409 phr->u.c.param1 = pC->u.clk.sample_rate;
410 else
411 found = 0;
412 break;
413 case HPI_CONTROL_PAD:
414
415 if (!(p_pad->field_valid_flags & (1 <<
416 HPI_CTL_ATTR_INDEX(phm->u.c.
417 attribute)))) {
418 phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
419 break;
420 }
421
422 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
423 phr->u.c.param1 = p_pad->pI;
424 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
425 phr->u.c.param1 = p_pad->pTY;
426 else {
427 unsigned int index =
428 HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1;
429 unsigned int offset = phm->u.c.param1;
430 unsigned int pad_string_len, field_size;
431 char *pad_string;
432 unsigned int tocopy;
433
434 HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n",
435 phm->u.c.attribute);
436
437 if (index > ARRAY_SIZE(pad_desc) - 1) {
438 phr->error =
439 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
440 break;
441 }
442
443 pad_string = ((char *)p_pad) + pad_desc[index].offset;
444 field_size = pad_desc[index].field_size;
445 /* Ensure null terminator */
446 pad_string[field_size - 1] = 0;
447
448 pad_string_len = strlen(pad_string) + 1;
449
450 if (offset > pad_string_len) {
451 phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
452 break;
453 }
454
455 tocopy = pad_string_len - offset;
456 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
457 tocopy = sizeof(phr->u.cu.chars8.sz_data);
458
459 HPI_DEBUG_LOG(VERBOSE,
460 "PADS memcpy(%d), offset %d \n", tocopy,
461 offset);
462 memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset],
463 tocopy);
464
465 phr->u.cu.chars8.remaining_chars =
466 pad_string_len - offset - tocopy;
467 }
468 break;
469 default:
470 found = 0;
471 break;
472 }
473
474 if (found)
475 HPI_DEBUG_LOG(VERBOSE,
476 "cached adap %d, ctl %d, type %d, attr %d\n",
477 phm->adapter_index, pI->control_index,
478 pI->control_type, phm->u.c.attribute);
479 else
480 HPI_DEBUG_LOG(VERBOSE,
481 "uncached adap %d, ctl %d, ctl type %d\n",
482 phm->adapter_index, pI->control_index,
483 pI->control_type);
484
485 if (found)
486 phr->size =
487 sizeof(struct hpi_response_header) +
488 sizeof(struct hpi_control_res);
489
490 return found;
491}
492
493/** Updates the cache with Set values.
494
495Only update if no error.
496Volume and Level return the limited values in the response, so use these
497Multiplexer does so use sent values
498*/
499void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
500 struct hpi_message *phm, struct hpi_response *phr)
501{
502 u16 control_index;
503 struct hpi_control_cache_single *pC;
504 struct hpi_control_cache_info *pI;
505
506 if (!find_control(phm, p_cache, &pI, &control_index))
507 return;
508
509 /* pC is the default cached control strucure.
510 May be cast to something else in the following switch statement.
511 */
512 pC = (struct hpi_control_cache_single *)pI;
513
514 switch (pI->control_type) {
515 case HPI_CONTROL_VOLUME:
516 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
517 pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
518 pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
519 }
520 break;
521 case HPI_CONTROL_MULTIPLEXER:
522 /* mux does not return its setting on Set command. */
523 if (phr->error)
524 return;
525 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
526 pC->u.x.source_node_type = (u16)phm->u.c.param1;
527 pC->u.x.source_node_index = (u16)phm->u.c.param2;
528 }
529 break;
530 case HPI_CONTROL_CHANNEL_MODE:
531 /* mode does not return its setting on Set command. */
532 if (phr->error)
533 return;
534 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
535 pC->u.m.mode = (u16)phm->u.c.param1;
536 break;
537 case HPI_CONTROL_LEVEL:
538 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
539 pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
540 pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
541 }
542 break;
543 case HPI_CONTROL_MICROPHONE:
544 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
545 pC->u.phantom_power.state = (u16)phm->u.c.param1;
546 break;
547 case HPI_CONTROL_AESEBU_TRANSMITTER:
548 if (phr->error)
549 return;
550 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
551 pC->u.aes3tx.format = phm->u.c.param1;
552 break;
553 case HPI_CONTROL_AESEBU_RECEIVER:
554 if (phr->error)
555 return;
556 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
557 pC->u.aes3rx.source = phm->u.c.param1;
558 break;
559 case HPI_CONTROL_SAMPLECLOCK:
560 if (phr->error)
561 return;
562 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
563 pC->u.clk.source = (u16)phm->u.c.param1;
564 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
565 pC->u.clk.source_index = (u16)phm->u.c.param1;
566 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
567 pC->u.clk.sample_rate = phm->u.c.param1;
568 break;
569 default:
570 break;
571 }
572}
573
574struct hpi_control_cache *hpi_alloc_control_cache(const u32
575 number_of_controls, const u32 size_in_bytes,
576 struct hpi_control_cache_info *pDSP_control_buffer)
577{
578 struct hpi_control_cache *p_cache =
579 kmalloc(sizeof(*p_cache), GFP_KERNEL);
580 p_cache->cache_size_in_bytes = size_in_bytes;
581 p_cache->control_count = number_of_controls;
582 p_cache->p_cache =
583 (struct hpi_control_cache_single *)pDSP_control_buffer;
584 p_cache->init = 0;
585 p_cache->p_info =
586 kmalloc(sizeof(*p_cache->p_info) * p_cache->control_count,
587 GFP_KERNEL);
588 return p_cache;
589}
590
591void hpi_free_control_cache(struct hpi_control_cache *p_cache)
592{
593 if ((p_cache->init) && (p_cache->p_info)) {
594 kfree(p_cache->p_info);
595 p_cache->p_info = NULL;
596 p_cache->init = 0;
597 kfree(p_cache);
598 }
599}
600
601static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
602{
603
604 switch (phm->function) {
605 case HPI_SUBSYS_OPEN:
606 case HPI_SUBSYS_CLOSE:
607 case HPI_SUBSYS_DRIVER_UNLOAD:
608 phr->error = 0;
609 break;
610 case HPI_SUBSYS_DRIVER_LOAD:
611 wipe_adapter_list();
612 hpios_alistlock_init(&adapters);
613 phr->error = 0;
614 break;
615 case HPI_SUBSYS_GET_INFO:
616 subsys_get_adapters(phr);
617 break;
618 case HPI_SUBSYS_CREATE_ADAPTER:
619 case HPI_SUBSYS_DELETE_ADAPTER:
620 phr->error = 0;
621 break;
622 default:
623 phr->error = HPI_ERROR_INVALID_FUNC;
624 break;
625 }
626}
627
628void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
629{
630 switch (phm->type) {
631 case HPI_TYPE_MESSAGE:
632 switch (phm->object) {
633 case HPI_OBJ_SUBSYSTEM:
634 subsys_message(phm, phr);
635 break;
636 }
637 break;
638
639 default:
640 phr->error = HPI_ERROR_INVALID_TYPE;
641 break;
642 }
643}
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h
new file mode 100644
index 000000000000..6229022f56cb
--- /dev/null
+++ b/sound/pci/asihpi/hpicmn.h
@@ -0,0 +1,64 @@
1/**
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19*/
20
21struct hpi_adapter_obj {
22 struct hpi_pci pci; /* PCI info - bus#,dev#,address etc */
23 u16 adapter_type; /* ASI6701 etc */
24 u16 index; /* */
25 u16 open; /* =1 when adapter open */
26 u16 mixer_open;
27
28 struct hpios_spinlock dsp_lock;
29
30 u16 dsp_crashed;
31 u16 has_control_cache;
32 void *priv;
33};
34
35struct hpi_control_cache {
36 u32 init; /**< indicates whether the
37 structures are initialized */
38 u32 control_count;
39 u32 cache_size_in_bytes;
40 struct hpi_control_cache_info
41 **p_info; /**< pointer to allocated memory of
42 lookup pointers. */
43 struct hpi_control_cache_single
44 *p_cache; /**< pointer to DSP's control cache. */
45};
46
47struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index);
48u16 hpi_add_adapter(struct hpi_adapter_obj *pao);
49
50void hpi_delete_adapter(struct hpi_adapter_obj *pao);
51
52short hpi_check_control_cache(struct hpi_control_cache *pC,
53 struct hpi_message *phm, struct hpi_response *phr);
54struct hpi_control_cache *hpi_alloc_control_cache(const u32
55 number_of_controls, const u32 size_in_bytes,
56 struct hpi_control_cache_info
57 *pDSP_control_buffer);
58void hpi_free_control_cache(struct hpi_control_cache *p_cache);
59
60void hpi_sync_control_cache(struct hpi_control_cache *pC,
61 struct hpi_message *phm, struct hpi_response *phr);
62u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr);
63short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
64 struct hpi_message *phm, void **p, unsigned int *pN);
diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c
new file mode 100644
index 000000000000..4cd85a401b34
--- /dev/null
+++ b/sound/pci/asihpi/hpidebug.c
@@ -0,0 +1,225 @@
1/************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Debug macro translation.
20
21************************************************************************/
22
23#include "hpi_internal.h"
24#include "hpidebug.h"
25
26/* Debug level; 0 quiet; 1 informative, 2 debug, 3 verbose debug. */
27int hpi_debug_level = HPI_DEBUG_LEVEL_DEFAULT;
28
29void hpi_debug_init(void)
30{
31 printk(KERN_INFO "debug start\n");
32}
33
34int hpi_debug_level_set(int level)
35{
36 int old_level;
37
38 old_level = hpi_debug_level;
39 hpi_debug_level = level;
40 return old_level;
41}
42
43int hpi_debug_level_get(void)
44{
45 return hpi_debug_level;
46}
47
48#ifdef HPIOS_DEBUG_PRINT
49/* implies OS has no printf-like function */
50#include <stdarg.h>
51
52void hpi_debug_printf(char *fmt, ...)
53{
54 va_list arglist;
55 char buffer[128];
56
57 va_start(arglist, fmt);
58
59 if (buffer[0])
60 HPIOS_DEBUG_PRINT(buffer);
61 va_end(arglist);
62}
63#endif
64
65struct treenode {
66 void *array;
67 unsigned int num_elements;
68};
69
70#define make_treenode_from_array(nodename, array) \
71static void *tmp_strarray_##nodename[] = array; \
72static struct treenode nodename = { \
73 &tmp_strarray_##nodename, \
74 ARRAY_SIZE(tmp_strarray_##nodename) \
75};
76
77#define get_treenode_elem(node_ptr, idx, type) \
78 (&(*((type *)(node_ptr)->array)[idx]))
79
80make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
81
82 make_treenode_from_array(hpi_subsys_strings, HPI_SUBSYS_STRINGS)
83 make_treenode_from_array(hpi_adapter_strings, HPI_ADAPTER_STRINGS)
84 make_treenode_from_array(hpi_istream_strings, HPI_ISTREAM_STRINGS)
85 make_treenode_from_array(hpi_ostream_strings, HPI_OSTREAM_STRINGS)
86 make_treenode_from_array(hpi_mixer_strings, HPI_MIXER_STRINGS)
87 make_treenode_from_array(hpi_node_strings,
88 {
89 "NODE is invalid object"})
90
91 make_treenode_from_array(hpi_control_strings, HPI_CONTROL_STRINGS)
92 make_treenode_from_array(hpi_nvmemory_strings, HPI_OBJ_STRINGS)
93 make_treenode_from_array(hpi_digitalio_strings, HPI_DIGITALIO_STRINGS)
94 make_treenode_from_array(hpi_watchdog_strings, HPI_WATCHDOG_STRINGS)
95 make_treenode_from_array(hpi_clock_strings, HPI_CLOCK_STRINGS)
96 make_treenode_from_array(hpi_profile_strings, HPI_PROFILE_STRINGS)
97 make_treenode_from_array(hpi_asyncevent_strings, HPI_ASYNCEVENT_STRINGS)
98#define HPI_FUNCTION_STRINGS \
99{ \
100 &hpi_subsys_strings,\
101 &hpi_adapter_strings,\
102 &hpi_ostream_strings,\
103 &hpi_istream_strings,\
104 &hpi_mixer_strings,\
105 &hpi_node_strings,\
106 &hpi_control_strings,\
107 &hpi_nvmemory_strings,\
108 &hpi_digitalio_strings,\
109 &hpi_watchdog_strings,\
110 &hpi_clock_strings,\
111 &hpi_profile_strings,\
112 &hpi_control_strings, \
113 &hpi_asyncevent_strings \
114};
115 make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
116
117 compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);
118
119static char *hpi_function_string(unsigned int function)
120{
121 unsigned int object;
122 struct treenode *tmp;
123
124 object = function / HPI_OBJ_FUNCTION_SPACING;
125 function = function - object * HPI_OBJ_FUNCTION_SPACING;
126
127 if (object == 0 || object == HPI_OBJ_NODE
128 || object > hpi_function_strings.num_elements)
129 return "invalid object";
130
131 tmp = get_treenode_elem(&hpi_function_strings, object - 1,
132 struct treenode *);
133
134 if (function == 0 || function > tmp->num_elements)
135 return "invalid function";
136
137 return get_treenode_elem(tmp, function - 1, char *);
138}
139
140void hpi_debug_message(struct hpi_message *phm, char *sz_fileline)
141{
142 if (phm) {
143 if ((phm->object <= HPI_OBJ_MAXINDEX) && phm->object) {
144 u16 index = 0;
145 u16 attrib = 0;
146 int is_control = 0;
147
148 index = phm->obj_index;
149 switch (phm->object) {
150 case HPI_OBJ_ADAPTER:
151 case HPI_OBJ_PROFILE:
152 break;
153 case HPI_OBJ_MIXER:
154 if (phm->function ==
155 HPI_MIXER_GET_CONTROL_BY_INDEX)
156 index = phm->u.m.control_index;
157 break;
158 case HPI_OBJ_OSTREAM:
159 case HPI_OBJ_ISTREAM:
160 break;
161
162 case HPI_OBJ_CONTROLEX:
163 case HPI_OBJ_CONTROL:
164 if (phm->version == 1)
165 attrib = HPI_CTL_ATTR(UNIVERSAL, 1);
166 else
167 attrib = phm->u.c.attribute;
168 is_control = 1;
169 break;
170 default:
171 break;
172 }
173
174 if (is_control && (attrib & 0xFF00)) {
175 int control_type = (attrib & 0xFF00) >> 8;
176 int attr_index = HPI_CTL_ATTR_INDEX(attrib);
177 /* note the KERN facility level
178 is in szFileline already */
179 printk("%s adapter %d %s "
180 "ctrl_index x%04x %s %d\n",
181 sz_fileline, phm->adapter_index,
182 hpi_function_string(phm->function),
183 index,
184 get_treenode_elem
185 (&hpi_control_type_strings,
186 control_type, char *),
187 attr_index);
188
189 } else
190 printk("%s adapter %d %s "
191 "idx x%04x attr x%04x \n",
192 sz_fileline, phm->adapter_index,
193 hpi_function_string(phm->function),
194 index, attrib);
195 } else {
196 printk("adap=%d, invalid obj=%d, func=0x%x\n",
197 phm->adapter_index, phm->object,
198 phm->function);
199 }
200 } else
201 printk(KERN_ERR
202 "NULL message pointer to hpi_debug_message!\n");
203}
204
205void hpi_debug_data(u16 *pdata, u32 len)
206{
207 u32 i;
208 int j;
209 int k;
210 int lines;
211 int cols = 8;
212
213 lines = (len + cols - 1) / cols;
214 if (lines > 8)
215 lines = 8;
216
217 for (i = 0, j = 0; j < lines; j++) {
218 printk(KERN_DEBUG "%p:", (pdata + i));
219
220 for (k = 0; k < cols && i < len; i++, k++)
221 printk("%s%04x", k == 0 ? "" : " ", pdata[i]);
222
223 printk("\n");
224 }
225}
diff --git a/sound/pci/asihpi/hpidebug.h b/sound/pci/asihpi/hpidebug.h
new file mode 100644
index 000000000000..44dccadcc25b
--- /dev/null
+++ b/sound/pci/asihpi/hpidebug.h
@@ -0,0 +1,385 @@
1/*****************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Debug macros.
20
21*****************************************************************************/
22
23#ifndef _HPIDEBUG_H
24#define _HPIDEBUG_H
25
26#include "hpi_internal.h"
27
28/* Define debugging levels. */
29enum { HPI_DEBUG_LEVEL_ERROR = 0, /* always log errors */
30 HPI_DEBUG_LEVEL_WARNING = 1,
31 HPI_DEBUG_LEVEL_NOTICE = 2,
32 HPI_DEBUG_LEVEL_INFO = 3,
33 HPI_DEBUG_LEVEL_DEBUG = 4,
34 HPI_DEBUG_LEVEL_VERBOSE = 5 /* same printk level as DEBUG */
35};
36
37#define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE
38
39/* an OS can define an extra flag string that is appended to
40 the start of each message, eg see hpios_linux.h */
41
42#ifdef SOURCEFILE_NAME
43#define FILE_LINE SOURCEFILE_NAME ":" __stringify(__LINE__) " "
44#else
45#define FILE_LINE __FILE__ ":" __stringify(__LINE__) " "
46#endif
47
48#if defined(HPI_DEBUG) && defined(_WINDOWS)
49#define HPI_DEBUGBREAK() debug_break()
50#else
51#define HPI_DEBUGBREAK()
52#endif
53
54#define HPI_DEBUG_ASSERT(expression) \
55 do { \
56 if (!(expression)) {\
57 printk(KERN_ERR FILE_LINE\
58 "ASSERT " __stringify(expression));\
59 HPI_DEBUGBREAK();\
60 } \
61 } while (0)
62
63#define HPI_DEBUG_LOG(level, ...) \
64 do { \
65 if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \
66 printk(HPI_DEBUG_FLAG_##level \
67 FILE_LINE __VA_ARGS__); \
68 } \
69 } while (0)
70
71void hpi_debug_init(void);
72int hpi_debug_level_set(int level);
73int hpi_debug_level_get(void);
74/* needed by Linux driver for dynamic debug level changes */
75extern int hpi_debug_level;
76
77void hpi_debug_message(struct hpi_message *phm, char *sz_fileline);
78
79void hpi_debug_data(u16 *pdata, u32 len);
80
81#define HPI_DEBUG_DATA(pdata, len) \
82 do { \
83 if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
84 hpi_debug_data(pdata, len); \
85 } while (0)
86
87#define HPI_DEBUG_MESSAGE(level, phm) \
88 do { \
89 if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \
90 hpi_debug_message(phm,HPI_DEBUG_FLAG_##level \
91 FILE_LINE __stringify(level));\
92 } \
93 } while (0)
94
95#define HPI_DEBUG_RESPONSE(phr) \
96 do { \
97 if ((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && (phr->error))\
98 HPI_DEBUG_LOG(ERROR, \
99 "HPI response - error# %d\n", \
100 phr->error); \
101 else if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
102 HPI_DEBUG_LOG(VERBOSE, "HPI response OK\n");\
103 } while (0)
104
105#ifndef compile_time_assert
106#define compile_time_assert(cond, msg) \
107 typedef char msg[(cond) ? 1 : -1]
108#endif
109
110 /* check that size is exactly some number */
111#define function_count_check(sym, size) \
112 compile_time_assert((sym##_FUNCTION_COUNT) == (size),\
113 strings_match_defs_##sym)
114
115/* These strings should be generated using a macro which defines
116 the corresponding symbol values. */
117#define HPI_OBJ_STRINGS \
118{ \
119 "HPI_OBJ_SUBSYSTEM", \
120 "HPI_OBJ_ADAPTER", \
121 "HPI_OBJ_OSTREAM", \
122 "HPI_OBJ_ISTREAM", \
123 "HPI_OBJ_MIXER", \
124 "HPI_OBJ_NODE", \
125 "HPI_OBJ_CONTROL", \
126 "HPI_OBJ_NVMEMORY", \
127 "HPI_OBJ_DIGITALIO", \
128 "HPI_OBJ_WATCHDOG", \
129 "HPI_OBJ_CLOCK", \
130 "HPI_OBJ_PROFILE", \
131 "HPI_OBJ_CONTROLEX" \
132}
133
134#define HPI_SUBSYS_STRINGS \
135{ \
136 "HPI_SUBSYS_OPEN", \
137 "HPI_SUBSYS_GET_VERSION", \
138 "HPI_SUBSYS_GET_INFO", \
139 "HPI_SUBSYS_FIND_ADAPTERS", \
140 "HPI_SUBSYS_CREATE_ADAPTER",\
141 "HPI_SUBSYS_CLOSE", \
142 "HPI_SUBSYS_DELETE_ADAPTER", \
143 "HPI_SUBSYS_DRIVER_LOAD", \
144 "HPI_SUBSYS_DRIVER_UNLOAD", \
145 "HPI_SUBSYS_READ_PORT_8", \
146 "HPI_SUBSYS_WRITE_PORT_8", \
147 "HPI_SUBSYS_GET_NUM_ADAPTERS",\
148 "HPI_SUBSYS_GET_ADAPTER", \
149 "HPI_SUBSYS_SET_NETWORK_INTERFACE"\
150}
151function_count_check(HPI_SUBSYS, 14);
152
153#define HPI_ADAPTER_STRINGS \
154{ \
155 "HPI_ADAPTER_OPEN", \
156 "HPI_ADAPTER_CLOSE", \
157 "HPI_ADAPTER_GET_INFO", \
158 "HPI_ADAPTER_GET_ASSERT", \
159 "HPI_ADAPTER_TEST_ASSERT", \
160 "HPI_ADAPTER_SET_MODE", \
161 "HPI_ADAPTER_GET_MODE", \
162 "HPI_ADAPTER_ENABLE_CAPABILITY",\
163 "HPI_ADAPTER_SELFTEST", \
164 "HPI_ADAPTER_FIND_OBJECT", \
165 "HPI_ADAPTER_QUERY_FLASH", \
166 "HPI_ADAPTER_START_FLASH", \
167 "HPI_ADAPTER_PROGRAM_FLASH", \
168 "HPI_ADAPTER_SET_PROPERTY", \
169 "HPI_ADAPTER_GET_PROPERTY", \
170 "HPI_ADAPTER_ENUM_PROPERTY", \
171 "HPI_ADAPTER_MODULE_INFO", \
172 "HPI_ADAPTER_DEBUG_READ" \
173}
174
175function_count_check(HPI_ADAPTER, 18);
176
177#define HPI_OSTREAM_STRINGS \
178{ \
179 "HPI_OSTREAM_OPEN", \
180 "HPI_OSTREAM_CLOSE", \
181 "HPI_OSTREAM_WRITE", \
182 "HPI_OSTREAM_START", \
183 "HPI_OSTREAM_STOP", \
184 "HPI_OSTREAM_RESET", \
185 "HPI_OSTREAM_GET_INFO", \
186 "HPI_OSTREAM_QUERY_FORMAT", \
187 "HPI_OSTREAM_DATA", \
188 "HPI_OSTREAM_SET_VELOCITY", \
189 "HPI_OSTREAM_SET_PUNCHINOUT", \
190 "HPI_OSTREAM_SINEGEN", \
191 "HPI_OSTREAM_ANC_RESET", \
192 "HPI_OSTREAM_ANC_GET_INFO", \
193 "HPI_OSTREAM_ANC_READ", \
194 "HPI_OSTREAM_SET_TIMESCALE",\
195 "HPI_OSTREAM_SET_FORMAT", \
196 "HPI_OSTREAM_HOSTBUFFER_ALLOC", \
197 "HPI_OSTREAM_HOSTBUFFER_FREE", \
198 "HPI_OSTREAM_GROUP_ADD",\
199 "HPI_OSTREAM_GROUP_GETMAP", \
200 "HPI_OSTREAM_GROUP_RESET", \
201 "HPI_OSTREAM_HOSTBUFFER_GET_INFO", \
202 "HPI_OSTREAM_WAIT_START", \
203}
204function_count_check(HPI_OSTREAM, 24);
205
206#define HPI_ISTREAM_STRINGS \
207{ \
208 "HPI_ISTREAM_OPEN", \
209 "HPI_ISTREAM_CLOSE", \
210 "HPI_ISTREAM_SET_FORMAT", \
211 "HPI_ISTREAM_READ", \
212 "HPI_ISTREAM_START", \
213 "HPI_ISTREAM_STOP", \
214 "HPI_ISTREAM_RESET", \
215 "HPI_ISTREAM_GET_INFO", \
216 "HPI_ISTREAM_QUERY_FORMAT", \
217 "HPI_ISTREAM_ANC_RESET", \
218 "HPI_ISTREAM_ANC_GET_INFO", \
219 "HPI_ISTREAM_ANC_WRITE", \
220 "HPI_ISTREAM_HOSTBUFFER_ALLOC",\
221 "HPI_ISTREAM_HOSTBUFFER_FREE", \
222 "HPI_ISTREAM_GROUP_ADD", \
223 "HPI_ISTREAM_GROUP_GETMAP", \
224 "HPI_ISTREAM_GROUP_RESET", \
225 "HPI_ISTREAM_HOSTBUFFER_GET_INFO", \
226 "HPI_ISTREAM_WAIT_START", \
227}
228function_count_check(HPI_ISTREAM, 19);
229
230#define HPI_MIXER_STRINGS \
231{ \
232 "HPI_MIXER_OPEN", \
233 "HPI_MIXER_CLOSE", \
234 "HPI_MIXER_GET_INFO", \
235 "HPI_MIXER_GET_NODE_INFO", \
236 "HPI_MIXER_GET_CONTROL", \
237 "HPI_MIXER_SET_CONNECTION", \
238 "HPI_MIXER_GET_CONNECTIONS", \
239 "HPI_MIXER_GET_CONTROL_BY_INDEX", \
240 "HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX", \
241 "HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES", \
242 "HPI_MIXER_STORE", \
243}
244function_count_check(HPI_MIXER, 11);
245
246#define HPI_CONTROL_STRINGS \
247{ \
248 "HPI_CONTROL_GET_INFO", \
249 "HPI_CONTROL_GET_STATE", \
250 "HPI_CONTROL_SET_STATE" \
251}
252function_count_check(HPI_CONTROL, 3);
253
254#define HPI_NVMEMORY_STRINGS \
255{ \
256 "HPI_NVMEMORY_OPEN", \
257 "HPI_NVMEMORY_READ_BYTE", \
258 "HPI_NVMEMORY_WRITE_BYTE" \
259}
260function_count_check(HPI_NVMEMORY, 3);
261
262#define HPI_DIGITALIO_STRINGS \
263{ \
264 "HPI_GPIO_OPEN", \
265 "HPI_GPIO_READ_BIT", \
266 "HPI_GPIO_WRITE_BIT", \
267 "HPI_GPIO_READ_ALL", \
268 "HPI_GPIO_WRITE_STATUS"\
269}
270function_count_check(HPI_GPIO, 5);
271
272#define HPI_WATCHDOG_STRINGS \
273{ \
274 "HPI_WATCHDOG_OPEN", \
275 "HPI_WATCHDOG_SET_TIME", \
276 "HPI_WATCHDOG_PING" \
277}
278
279#define HPI_CLOCK_STRINGS \
280{ \
281 "HPI_CLOCK_OPEN", \
282 "HPI_CLOCK_SET_TIME", \
283 "HPI_CLOCK_GET_TIME" \
284}
285
286#define HPI_PROFILE_STRINGS \
287{ \
288 "HPI_PROFILE_OPEN_ALL", \
289 "HPI_PROFILE_START_ALL", \
290 "HPI_PROFILE_STOP_ALL", \
291 "HPI_PROFILE_GET", \
292 "HPI_PROFILE_GET_IDLECOUNT", \
293 "HPI_PROFILE_GET_NAME", \
294 "HPI_PROFILE_GET_UTILIZATION" \
295}
296function_count_check(HPI_PROFILE, 7);
297
298#define HPI_ASYNCEVENT_STRINGS \
299{ \
300 "HPI_ASYNCEVENT_OPEN",\
301 "HPI_ASYNCEVENT_CLOSE ",\
302 "HPI_ASYNCEVENT_WAIT",\
303 "HPI_ASYNCEVENT_GETCOUNT",\
304 "HPI_ASYNCEVENT_GET",\
305 "HPI_ASYNCEVENT_SENDEVENTS"\
306}
307function_count_check(HPI_ASYNCEVENT, 6);
308
309#define HPI_CONTROL_TYPE_STRINGS \
310{ \
311 "null control", \
312 "HPI_CONTROL_CONNECTION", \
313 "HPI_CONTROL_VOLUME", \
314 "HPI_CONTROL_METER", \
315 "HPI_CONTROL_MUTE", \
316 "HPI_CONTROL_MULTIPLEXER", \
317 "HPI_CONTROL_AESEBU_TRANSMITTER", \
318 "HPI_CONTROL_AESEBU_RECEIVER", \
319 "HPI_CONTROL_LEVEL", \
320 "HPI_CONTROL_TUNER", \
321 "HPI_CONTROL_ONOFFSWITCH", \
322 "HPI_CONTROL_VOX", \
323 "HPI_CONTROL_AES18_TRANSMITTER", \
324 "HPI_CONTROL_AES18_RECEIVER", \
325 "HPI_CONTROL_AES18_BLOCKGENERATOR", \
326 "HPI_CONTROL_CHANNEL_MODE", \
327 "HPI_CONTROL_BITSTREAM", \
328 "HPI_CONTROL_SAMPLECLOCK", \
329 "HPI_CONTROL_MICROPHONE", \
330 "HPI_CONTROL_PARAMETRIC_EQ", \
331 "HPI_CONTROL_COMPANDER", \
332 "HPI_CONTROL_COBRANET", \
333 "HPI_CONTROL_TONE_DETECT", \
334 "HPI_CONTROL_SILENCE_DETECT", \
335 "HPI_CONTROL_PAD", \
336 "HPI_CONTROL_SRC" ,\
337 "HPI_CONTROL_UNIVERSAL" \
338}
339
340compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
341 controltype_strings_match_defs);
342
343#define HPI_SOURCENODE_STRINGS \
344{ \
345 "no source", \
346 "HPI_SOURCENODE_OSTREAM", \
347 "HPI_SOURCENODE_LINEIN", \
348 "HPI_SOURCENODE_AESEBU_IN", \
349 "HPI_SOURCENODE_TUNER", \
350 "HPI_SOURCENODE_RF", \
351 "HPI_SOURCENODE_CLOCK_SOURCE", \
352 "HPI_SOURCENODE_RAW_BITSTREAM", \
353 "HPI_SOURCENODE_MICROPHONE", \
354 "HPI_SOURCENODE_COBRANET", \
355 "HPI_SOURCENODE_ANALOG", \
356 "HPI_SOURCENODE_ADAPTER" \
357}
358
359compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) ==
360 (12), sourcenode_strings_match_defs);
361
362#define HPI_DESTNODE_STRINGS \
363{ \
364 "no destination", \
365 "HPI_DESTNODE_ISTREAM", \
366 "HPI_DESTNODE_LINEOUT", \
367 "HPI_DESTNODE_AESEBU_OUT", \
368 "HPI_DESTNODE_RF", \
369 "HPI_DESTNODE_SPEAKER", \
370 "HPI_DESTNODE_COBRANET", \
371 "HPI_DESTNODE_ANALOG" \
372}
373compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_BASE + 1) == (8),
374 destnode_strings_match_defs);
375
376#define HPI_CONTROL_CHANNEL_MODE_STRINGS \
377{ \
378 "XXX HPI_CHANNEL_MODE_ERROR XXX", \
379 "HPI_CHANNEL_MODE_NORMAL", \
380 "HPI_CHANNEL_MODE_SWAP", \
381 "HPI_CHANNEL_MODE_LEFT_ONLY", \
382 "HPI_CHANNEL_MODE_RIGHT_ONLY" \
383}
384
385#endif /* _HPIDEBUG_H */
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
new file mode 100644
index 000000000000..9b10d9a5c255
--- /dev/null
+++ b/sound/pci/asihpi/hpidspcd.c
@@ -0,0 +1,172 @@
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
21Functions for reading DSP code to load into DSP
22
23(Linux only:) If DSPCODE_FIRMWARE_LOADER is defined, code is read using
24hotplug firmware loader from individual dsp code files
25
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/***********************************************************************/
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
47struct 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/*-------------------------------------------------------------------*/
65short 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
122error2:
123 release_firmware(ps_firmware);
124error1:
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/*-------------------------------------------------------------------*/
131void 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/*-------------------------------------------------------------------*/
141void 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/*-------------------------------------------------------------------*/
148short 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/*-------------------------------------------------------------------*/
160short 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}
diff --git a/sound/pci/asihpi/hpidspcd.h b/sound/pci/asihpi/hpidspcd.h
new file mode 100644
index 000000000000..d7c240398225
--- /dev/null
+++ b/sound/pci/asihpi/hpidspcd.h
@@ -0,0 +1,104 @@
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
21Functions for reading DSP code to load into DSP
22
23 hpi_dspcode_defines HPI DSP code loading method
24Define exactly one of these to select how the DSP code is supplied to
25the adapter.
26
27End users writing applications that use the HPI interface do not have to
28use any of the below defines; they are only necessary for building drivers
29
30HPI_DSPCODE_FILE:
31DSP code is supplied as a file that is opened and read from by the driver.
32
33HPI_DSPCODE_FIRMWARE:
34DSP code is read using the hotplug firmware loader module.
35 Only valid when compiling the HPI kernel driver under Linux.
36*/
37/***********************************************************************/
38#ifndef _HPIDSPCD_H_
39#define _HPIDSPCD_H_
40
41#include "hpi_internal.h"
42
43#ifndef DISABLE_PRAGMA_PACK1
44#pragma pack(push, 1)
45#endif
46
47/** Descriptor for dspcode from firmware loader */
48struct dsp_code {
49 /** Firmware descriptor */
50 const struct firmware *ps_firmware;
51 struct pci_dev *ps_dev;
52 /** Expected number of words in the whole dsp code,INCL header */
53 long int block_length;
54 /** Number of words read so far */
55 long int word_count;
56 /** Version read from dsp code file */
57 u32 version;
58 /** CRC read from dsp code file */
59 u32 crc;
60};
61
62#ifndef DISABLE_PRAGMA_PACK1
63#pragma pack(pop)
64#endif
65
66/** Prepare *psDspCode to refer to the requuested adapter.
67 Searches the file, or selects the appropriate linked array
68
69\return 0 for success, or error code if requested code is not available
70*/
71short hpi_dsp_code_open(
72 /** Code identifier, usually adapter family */
73 u32 adapter,
74 /** Pointer to DSP code control structure */
75 struct dsp_code *ps_dsp_code,
76 /** Pointer to dword to receive OS specific error code */
77 u32 *pos_error_code);
78
79/** Close the DSP code file */
80void hpi_dsp_code_close(struct dsp_code *ps_dsp_code);
81
82/** Rewind to the beginning of the DSP code file (for verify) */
83void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code);
84
85/** Read one word from the dsp code file
86 \return 0 for success, or error code if eof, or block length exceeded
87*/
88short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code,
89 /**< DSP code descriptor */
90 u32 *pword /**< where to store the read word */
91 );
92
93/** Get a block of dsp code into an internal buffer, and provide a pointer to
94that buffer. (If dsp code is already an array in memory, it is referenced,
95not copied.)
96
97\return Error if requested number of words are not available
98*/
99short hpi_dsp_code_read_block(size_t words_requested,
100 struct dsp_code *ps_dsp_code,
101 /* Pointer to store (Pointer to code buffer) */
102 u32 **ppblock);
103
104#endif
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
new file mode 100644
index 000000000000..254c580db639
--- /dev/null
+++ b/sound/pci/asihpi/hpifunc.c
@@ -0,0 +1,3864 @@
1
2#include "hpi_internal.h"
3#include "hpimsginit.h"
4
5#include "hpidebug.h"
6
7struct hpi_handle {
8 unsigned int obj_index:12;
9 unsigned int obj_type:4;
10 unsigned int adapter_index:14;
11 unsigned int spare:1;
12 unsigned int read_only:1;
13};
14
15union handle_word {
16 struct hpi_handle h;
17 u32 w;
18};
19
20u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index,
21 const u16 object_index)
22{
23 union handle_word handle;
24
25 handle.h.adapter_index = adapter_index;
26 handle.h.spare = 0;
27 handle.h.read_only = 0;
28 handle.h.obj_type = c_object;
29 handle.h.obj_index = object_index;
30 return handle.w;
31}
32
33void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index,
34 u16 *pw_object_index)
35{
36 union handle_word uhandle;
37 uhandle.w = handle;
38
39 if (pw_adapter_index)
40 *pw_adapter_index = (u16)uhandle.h.adapter_index;
41 if (pw_object_index)
42 *pw_object_index = (u16)uhandle.h.obj_index;
43}
44
45char hpi_handle_object(const u32 handle)
46{
47 union handle_word uhandle;
48 uhandle.w = handle;
49 return (char)uhandle.h.obj_type;
50}
51
52#define u32TOINDEX(h, i1) \
53do {\
54 if (h == 0) \
55 return HPI_ERROR_INVALID_OBJ; \
56 else \
57 hpi_handle_to_indexes(h, i1, NULL); \
58} while (0)
59
60#define u32TOINDEXES(h, i1, i2) \
61do {\
62 if (h == 0) \
63 return HPI_ERROR_INVALID_OBJ; \
64 else \
65 hpi_handle_to_indexes(h, i1, i2);\
66} while (0)
67
68void hpi_format_to_msg(struct hpi_msg_format *pMF,
69 const struct hpi_format *pF)
70{
71 pMF->sample_rate = pF->sample_rate;
72 pMF->bit_rate = pF->bit_rate;
73 pMF->attributes = pF->attributes;
74 pMF->channels = pF->channels;
75 pMF->format = pF->format;
76}
77
78static void hpi_msg_to_format(struct hpi_format *pF,
79 struct hpi_msg_format *pMF)
80{
81 pF->sample_rate = pMF->sample_rate;
82 pF->bit_rate = pMF->bit_rate;
83 pF->attributes = pMF->attributes;
84 pF->channels = pMF->channels;
85 pF->format = pMF->format;
86 pF->mode_legacy = 0;
87 pF->unused = 0;
88}
89
90void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR)
91{
92 pSR->u.legacy_stream_info.auxiliary_data_available =
93 pSR->u.stream_info.auxiliary_data_available;
94 pSR->u.legacy_stream_info.state = pSR->u.stream_info.state;
95}
96
97static struct hpi_hsubsys gh_subsys;
98
99struct hpi_hsubsys *hpi_subsys_create(void
100 )
101{
102 struct hpi_message hm;
103 struct hpi_response hr;
104
105 memset(&gh_subsys, 0, sizeof(struct hpi_hsubsys));
106
107 {
108 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
109 HPI_SUBSYS_OPEN);
110 hpi_send_recv(&hm, &hr);
111
112 if (hr.error == 0)
113 return &gh_subsys;
114
115 }
116 return NULL;
117}
118
119void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys)
120{
121 struct hpi_message hm;
122 struct hpi_response hr;
123
124 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
125 HPI_SUBSYS_CLOSE);
126 hpi_send_recv(&hm, &hr);
127
128}
129
130u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys, u32 *pversion)
131{
132 struct hpi_message hm;
133 struct hpi_response hr;
134
135 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
136 HPI_SUBSYS_GET_VERSION);
137 hpi_send_recv(&hm, &hr);
138 *pversion = hr.u.s.version;
139 return hr.error;
140}
141
142u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys,
143 u32 *pversion_ex)
144{
145 struct hpi_message hm;
146 struct hpi_response hr;
147
148 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
149 HPI_SUBSYS_GET_VERSION);
150 hpi_send_recv(&hm, &hr);
151 *pversion_ex = hr.u.s.data;
152 return hr.error;
153}
154
155u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion,
156 u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length)
157{
158 struct hpi_message hm;
159 struct hpi_response hr;
160 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
161 HPI_SUBSYS_GET_INFO);
162
163 hpi_send_recv(&hm, &hr);
164
165 *pversion = hr.u.s.version;
166 if (list_length > HPI_MAX_ADAPTERS)
167 memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list,
168 HPI_MAX_ADAPTERS);
169 else
170 memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list, list_length);
171 *pw_num_adapters = hr.u.s.num_adapters;
172 return hr.error;
173}
174
175u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys,
176 u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length)
177{
178 struct hpi_message hm;
179 struct hpi_response hr;
180 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
181 HPI_SUBSYS_FIND_ADAPTERS);
182
183 hpi_send_recv(&hm, &hr);
184
185 if (list_length > HPI_MAX_ADAPTERS) {
186 memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list,
187 HPI_MAX_ADAPTERS * sizeof(u16));
188 memset(&aw_adapter_list[HPI_MAX_ADAPTERS], 0,
189 (list_length - HPI_MAX_ADAPTERS) * sizeof(u16));
190 } else
191 memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list,
192 list_length * sizeof(u16));
193 *pw_num_adapters = hr.u.s.num_adapters;
194
195 return hr.error;
196}
197
198u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys,
199 const struct hpi_resource *p_resource, u16 *pw_adapter_index)
200{
201 struct hpi_message hm;
202 struct hpi_response hr;
203
204 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
205 HPI_SUBSYS_CREATE_ADAPTER);
206 hm.u.s.resource = *p_resource;
207
208 hpi_send_recv(&hm, &hr);
209
210 *pw_adapter_index = hr.u.s.adapter_index;
211 return hr.error;
212}
213
214u16 hpi_subsys_delete_adapter(const struct hpi_hsubsys *ph_subsys,
215 u16 adapter_index)
216{
217 struct hpi_message hm;
218 struct hpi_response hr;
219 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
220 HPI_SUBSYS_DELETE_ADAPTER);
221 hm.adapter_index = adapter_index;
222 hpi_send_recv(&hm, &hr);
223 return hr.error;
224}
225
226u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys,
227 int *pn_num_adapters)
228{
229 struct hpi_message hm;
230 struct hpi_response hr;
231 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
232 HPI_SUBSYS_GET_NUM_ADAPTERS);
233 hpi_send_recv(&hm, &hr);
234 *pn_num_adapters = (int)hr.u.s.num_adapters;
235 return hr.error;
236}
237
238u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator,
239 u32 *padapter_index, u16 *pw_adapter_type)
240{
241 struct hpi_message hm;
242 struct hpi_response hr;
243 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
244 HPI_SUBSYS_GET_ADAPTER);
245 hm.adapter_index = (u16)iterator;
246 hpi_send_recv(&hm, &hr);
247 *padapter_index = (int)hr.u.s.adapter_index;
248 *pw_adapter_type = hr.u.s.aw_adapter_list[0];
249 return hr.error;
250}
251
252u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys,
253 const char *sz_interface)
254{
255 struct hpi_message hm;
256 struct hpi_response hr;
257 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
258 HPI_SUBSYS_SET_NETWORK_INTERFACE);
259 if (sz_interface == NULL)
260 return HPI_ERROR_INVALID_RESOURCE;
261 hm.u.s.resource.r.net_if = sz_interface;
262 hpi_send_recv(&hm, &hr);
263 return hr.error;
264}
265
266u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index)
267{
268 struct hpi_message hm;
269 struct hpi_response hr;
270 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
271 HPI_ADAPTER_OPEN);
272 hm.adapter_index = adapter_index;
273
274 hpi_send_recv(&hm, &hr);
275
276 return hr.error;
277
278}
279
280u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index)
281{
282 struct hpi_message hm;
283 struct hpi_response hr;
284 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
285 HPI_ADAPTER_CLOSE);
286 hm.adapter_index = adapter_index;
287
288 hpi_send_recv(&hm, &hr);
289
290 return hr.error;
291}
292
293u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys,
294 u16 adapter_index, u32 adapter_mode)
295{
296 return hpi_adapter_set_mode_ex(ph_subsys, adapter_index, adapter_mode,
297 HPI_ADAPTER_MODE_SET);
298}
299
300u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
301 u16 adapter_index, u32 adapter_mode, u16 query_or_set)
302{
303 struct hpi_message hm;
304 struct hpi_response hr;
305 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
306 HPI_ADAPTER_SET_MODE);
307 hm.adapter_index = adapter_index;
308 hm.u.a.adapter_mode = adapter_mode;
309 hm.u.a.assert_id = query_or_set;
310 hpi_send_recv(&hm, &hr);
311 return hr.error;
312}
313
314u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys,
315 u16 adapter_index, u32 *padapter_mode)
316{
317 struct hpi_message hm;
318 struct hpi_response hr;
319 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
320 HPI_ADAPTER_GET_MODE);
321 hm.adapter_index = adapter_index;
322 hpi_send_recv(&hm, &hr);
323 if (padapter_mode)
324 *padapter_mode = hr.u.a.serial_number;
325 return hr.error;
326}
327
328u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys,
329 u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams,
330 u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type)
331{
332 struct hpi_message hm;
333 struct hpi_response hr;
334 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
335 HPI_ADAPTER_GET_INFO);
336 hm.adapter_index = adapter_index;
337
338 hpi_send_recv(&hm, &hr);
339
340 *pw_adapter_type = hr.u.a.adapter_type;
341 *pw_num_outstreams = hr.u.a.num_outstreams;
342 *pw_num_instreams = hr.u.a.num_instreams;
343 *pw_version = hr.u.a.version;
344 *pserial_number = hr.u.a.serial_number;
345 return hr.error;
346}
347
348u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys,
349 u16 adapter_index, u16 module_index, u16 *pw_num_outputs,
350 u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number,
351 u16 *pw_module_type, u32 *ph_module)
352{
353 struct hpi_message hm;
354 struct hpi_response hr;
355
356 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
357 HPI_ADAPTER_MODULE_INFO);
358 hm.adapter_index = adapter_index;
359 hm.u.ax.module_info.index = module_index;
360
361 hpi_send_recv(&hm, &hr);
362
363 *pw_module_type = hr.u.a.adapter_type;
364 *pw_num_outputs = hr.u.a.num_outstreams;
365 *pw_num_inputs = hr.u.a.num_instreams;
366 *pw_version = hr.u.a.version;
367 *pserial_number = hr.u.a.serial_number;
368 *ph_module = 0;
369
370 return hr.error;
371}
372
373u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys,
374 u16 adapter_index, u16 *assert_present, char *psz_assert,
375 u16 *pw_line_number)
376{
377 struct hpi_message hm;
378 struct hpi_response hr;
379 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
380 HPI_ADAPTER_GET_ASSERT);
381 hm.adapter_index = adapter_index;
382 hpi_send_recv(&hm, &hr);
383
384 *assert_present = 0;
385
386 if (!hr.error) {
387
388 *pw_line_number = (u16)hr.u.a.serial_number;
389 if (*pw_line_number) {
390
391 int i;
392 char *src = (char *)hr.u.a.sz_adapter_assert;
393 char *dst = psz_assert;
394
395 *assert_present = 1;
396
397 for (i = 0; i < HPI_STRING_LEN; i++) {
398 char c;
399 c = *src++;
400 *dst++ = c;
401 if (c == 0)
402 break;
403 }
404
405 }
406 }
407 return hr.error;
408}
409
410u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys,
411 u16 adapter_index, u16 *assert_present, char *psz_assert,
412 u32 *pline_number, u16 *pw_assert_on_dsp)
413{
414 struct hpi_message hm;
415 struct hpi_response hr;
416 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
417 HPI_ADAPTER_GET_ASSERT);
418 hm.adapter_index = adapter_index;
419
420 hpi_send_recv(&hm, &hr);
421
422 *assert_present = 0;
423
424 if (!hr.error) {
425
426 *pline_number = hr.u.a.serial_number;
427
428 *assert_present = hr.u.a.adapter_type;
429
430 *pw_assert_on_dsp = hr.u.a.adapter_index;
431
432 if (!*assert_present && *pline_number)
433
434 *assert_present = 1;
435
436 if (*assert_present) {
437
438 int i;
439 char *src = (char *)hr.u.a.sz_adapter_assert;
440 char *dst = psz_assert;
441
442 for (i = 0; i < HPI_STRING_LEN; i++) {
443 char c;
444 c = *src++;
445 *dst++ = c;
446 if (c == 0)
447 break;
448 }
449
450 } else {
451 *psz_assert = 0;
452 }
453 }
454 return hr.error;
455}
456
457u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys,
458 u16 adapter_index, u16 assert_id)
459{
460 struct hpi_message hm;
461 struct hpi_response hr;
462 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
463 HPI_ADAPTER_TEST_ASSERT);
464 hm.adapter_index = adapter_index;
465 hm.u.a.assert_id = assert_id;
466
467 hpi_send_recv(&hm, &hr);
468
469 return hr.error;
470}
471
472u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys,
473 u16 adapter_index, u16 capability, u32 key)
474{
475 struct hpi_message hm;
476 struct hpi_response hr;
477 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
478 HPI_ADAPTER_ENABLE_CAPABILITY);
479 hm.adapter_index = adapter_index;
480 hm.u.a.assert_id = capability;
481 hm.u.a.adapter_mode = key;
482
483 hpi_send_recv(&hm, &hr);
484
485 return hr.error;
486}
487
488u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys,
489 u16 adapter_index)
490{
491 struct hpi_message hm;
492 struct hpi_response hr;
493 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
494 HPI_ADAPTER_SELFTEST);
495 hm.adapter_index = adapter_index;
496 hpi_send_recv(&hm, &hr);
497 return hr.error;
498}
499
500u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
501 u16 adapter_index, u32 dsp_address, char *p_buffer, int *count_bytes)
502{
503 struct hpi_message hm;
504 struct hpi_response hr;
505 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
506 HPI_ADAPTER_DEBUG_READ);
507
508 hr.size = sizeof(hr);
509
510 hm.adapter_index = adapter_index;
511 hm.u.ax.debug_read.dsp_address = dsp_address;
512
513 if (*count_bytes > sizeof(hr.u.bytes))
514 *count_bytes = sizeof(hr.u.bytes);
515
516 hm.u.ax.debug_read.count_bytes = *count_bytes;
517
518 hpi_send_recv(&hm, &hr);
519
520 if (!hr.error) {
521 *count_bytes = hr.size - 12;
522 memcpy(p_buffer, &hr.u.bytes, *count_bytes);
523 } else
524 *count_bytes = 0;
525 return hr.error;
526}
527
528u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys,
529 u16 adapter_index, u16 property, u16 parameter1, u16 parameter2)
530{
531 struct hpi_message hm;
532 struct hpi_response hr;
533 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
534 HPI_ADAPTER_SET_PROPERTY);
535 hm.adapter_index = adapter_index;
536 hm.u.ax.property_set.property = property;
537 hm.u.ax.property_set.parameter1 = parameter1;
538 hm.u.ax.property_set.parameter2 = parameter2;
539
540 hpi_send_recv(&hm, &hr);
541
542 return hr.error;
543}
544
545u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys,
546 u16 adapter_index, u16 property, u16 *pw_parameter1,
547 u16 *pw_parameter2)
548{
549 struct hpi_message hm;
550 struct hpi_response hr;
551 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
552 HPI_ADAPTER_GET_PROPERTY);
553 hm.adapter_index = adapter_index;
554 hm.u.ax.property_set.property = property;
555
556 hpi_send_recv(&hm, &hr);
557 if (!hr.error) {
558 if (pw_parameter1)
559 *pw_parameter1 = hr.u.ax.property_get.parameter1;
560 if (pw_parameter2)
561 *pw_parameter2 = hr.u.ax.property_get.parameter2;
562 }
563
564 return hr.error;
565}
566
567u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys,
568 u16 adapter_index, u16 index, u16 what_to_enumerate,
569 u16 property_index, u32 *psetting)
570{
571 return 0;
572}
573
574u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
575 u32 sample_rate, u32 bit_rate, u32 attributes)
576{
577 u16 error = 0;
578 struct hpi_msg_format fmt;
579
580 switch (channels) {
581 case 1:
582 case 2:
583 case 4:
584 case 6:
585 case 8:
586 case 16:
587 break;
588 default:
589 error = HPI_ERROR_INVALID_CHANNELS;
590 return error;
591 }
592 fmt.channels = channels;
593
594 switch (format) {
595 case HPI_FORMAT_PCM16_SIGNED:
596 case HPI_FORMAT_PCM24_SIGNED:
597 case HPI_FORMAT_PCM32_SIGNED:
598 case HPI_FORMAT_PCM32_FLOAT:
599 case HPI_FORMAT_PCM16_BIGENDIAN:
600 case HPI_FORMAT_PCM8_UNSIGNED:
601 case HPI_FORMAT_MPEG_L1:
602 case HPI_FORMAT_MPEG_L2:
603 case HPI_FORMAT_MPEG_L3:
604 case HPI_FORMAT_DOLBY_AC2:
605 case HPI_FORMAT_AA_TAGIT1_HITS:
606 case HPI_FORMAT_AA_TAGIT1_INSERTS:
607 case HPI_FORMAT_RAW_BITSTREAM:
608 case HPI_FORMAT_AA_TAGIT1_HITS_EX1:
609 case HPI_FORMAT_OEM1:
610 case HPI_FORMAT_OEM2:
611 break;
612 default:
613 error = HPI_ERROR_INVALID_FORMAT;
614 return error;
615 }
616 fmt.format = format;
617
618 if (sample_rate < 8000L) {
619 error = HPI_ERROR_INCOMPATIBLE_SAMPLERATE;
620 sample_rate = 8000L;
621 }
622 if (sample_rate > 200000L) {
623 error = HPI_ERROR_INCOMPATIBLE_SAMPLERATE;
624 sample_rate = 200000L;
625 }
626 fmt.sample_rate = sample_rate;
627
628 switch (format) {
629 case HPI_FORMAT_MPEG_L1:
630 case HPI_FORMAT_MPEG_L2:
631 case HPI_FORMAT_MPEG_L3:
632 fmt.bit_rate = bit_rate;
633 break;
634 case HPI_FORMAT_PCM16_SIGNED:
635 case HPI_FORMAT_PCM16_BIGENDIAN:
636 fmt.bit_rate = channels * sample_rate * 2;
637 break;
638 case HPI_FORMAT_PCM32_SIGNED:
639 case HPI_FORMAT_PCM32_FLOAT:
640 fmt.bit_rate = channels * sample_rate * 4;
641 break;
642 case HPI_FORMAT_PCM8_UNSIGNED:
643 fmt.bit_rate = channels * sample_rate;
644 break;
645 default:
646 fmt.bit_rate = 0;
647 }
648
649 switch (format) {
650 case HPI_FORMAT_MPEG_L2:
651 if ((channels == 1)
652 && (attributes != HPI_MPEG_MODE_DEFAULT)) {
653 attributes = HPI_MPEG_MODE_DEFAULT;
654 error = HPI_ERROR_INVALID_FORMAT;
655 } else if (attributes > HPI_MPEG_MODE_DUALCHANNEL) {
656 attributes = HPI_MPEG_MODE_DEFAULT;
657 error = HPI_ERROR_INVALID_FORMAT;
658 }
659 fmt.attributes = attributes;
660 break;
661 default:
662 fmt.attributes = attributes;
663 }
664
665 hpi_msg_to_format(p_format, &fmt);
666 return error;
667}
668
669u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format,
670 u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size)
671{
672
673 u32 bytes_per_second;
674 u32 size;
675 u16 channels;
676 struct hpi_format *pF = p_format;
677
678 channels = pF->channels;
679
680 switch (pF->format) {
681 case HPI_FORMAT_PCM16_BIGENDIAN:
682 case HPI_FORMAT_PCM16_SIGNED:
683 bytes_per_second = pF->sample_rate * 2L * channels;
684 break;
685 case HPI_FORMAT_PCM24_SIGNED:
686 bytes_per_second = pF->sample_rate * 3L * channels;
687 break;
688 case HPI_FORMAT_PCM32_SIGNED:
689 case HPI_FORMAT_PCM32_FLOAT:
690 bytes_per_second = pF->sample_rate * 4L * channels;
691 break;
692 case HPI_FORMAT_PCM8_UNSIGNED:
693 bytes_per_second = pF->sample_rate * 1L * channels;
694 break;
695 case HPI_FORMAT_MPEG_L1:
696 case HPI_FORMAT_MPEG_L2:
697 case HPI_FORMAT_MPEG_L3:
698 bytes_per_second = pF->bit_rate / 8L;
699 break;
700 case HPI_FORMAT_DOLBY_AC2:
701
702 bytes_per_second = 256000L / 8L;
703 break;
704 default:
705 return HPI_ERROR_INVALID_FORMAT;
706 }
707 size = (bytes_per_second * host_polling_rate_in_milli_seconds * 2) /
708 1000L;
709
710 *recommended_buffer_size =
711 roundup_pow_of_two(((size + 4095L) & ~4095L));
712 return 0;
713}
714
715u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
716 u16 outstream_index, u32 *ph_outstream)
717{
718 struct hpi_message hm;
719 struct hpi_response hr;
720 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
721 HPI_OSTREAM_OPEN);
722 hm.adapter_index = adapter_index;
723 hm.obj_index = outstream_index;
724
725 hpi_send_recv(&hm, &hr);
726
727 if (hr.error == 0)
728 *ph_outstream =
729 hpi_indexes_to_handle(HPI_OBJ_OSTREAM, adapter_index,
730 outstream_index);
731 else
732 *ph_outstream = 0;
733 return hr.error;
734}
735
736u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
737{
738 struct hpi_message hm;
739 struct hpi_response hr;
740
741 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
742 HPI_OSTREAM_HOSTBUFFER_FREE);
743 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
744 hpi_send_recv(&hm, &hr);
745
746 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
747 HPI_OSTREAM_GROUP_RESET);
748 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
749 hpi_send_recv(&hm, &hr);
750
751 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
752 HPI_OSTREAM_CLOSE);
753 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
754 hpi_send_recv(&hm, &hr);
755
756 return hr.error;
757}
758
759u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
760 u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play,
761 u32 *psamples_played, u32 *pauxiliary_data_to_play)
762{
763 struct hpi_message hm;
764 struct hpi_response hr;
765 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
766 HPI_OSTREAM_GET_INFO);
767 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
768
769 hpi_send_recv(&hm, &hr);
770
771 if (pw_state)
772 *pw_state = hr.u.d.u.stream_info.state;
773 if (pbuffer_size)
774 *pbuffer_size = hr.u.d.u.stream_info.buffer_size;
775 if (pdata_to_play)
776 *pdata_to_play = hr.u.d.u.stream_info.data_available;
777 if (psamples_played)
778 *psamples_played = hr.u.d.u.stream_info.samples_transferred;
779 if (pauxiliary_data_to_play)
780 *pauxiliary_data_to_play =
781 hr.u.d.u.stream_info.auxiliary_data_available;
782 return hr.error;
783}
784
785u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys,
786 u32 h_outstream, const u8 *pb_data, u32 bytes_to_write,
787 const struct hpi_format *p_format)
788{
789 struct hpi_message hm;
790 struct hpi_response hr;
791 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
792 HPI_OSTREAM_WRITE);
793 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
794 hm.u.d.u.data.pb_data = (u8 *)pb_data;
795 hm.u.d.u.data.data_size = bytes_to_write;
796
797 hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
798
799 hpi_send_recv(&hm, &hr);
800
801 return hr.error;
802}
803
804u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
805{
806 struct hpi_message hm;
807 struct hpi_response hr;
808 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
809 HPI_OSTREAM_START);
810 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
811
812 hpi_send_recv(&hm, &hr);
813
814 return hr.error;
815}
816
817u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys,
818 u32 h_outstream)
819{
820 struct hpi_message hm;
821 struct hpi_response hr;
822 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
823 HPI_OSTREAM_WAIT_START);
824 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
825
826 hpi_send_recv(&hm, &hr);
827
828 return hr.error;
829}
830
831u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
832{
833 struct hpi_message hm;
834 struct hpi_response hr;
835 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
836 HPI_OSTREAM_STOP);
837 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
838
839 hpi_send_recv(&hm, &hr);
840
841 return hr.error;
842}
843
844u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys,
845 u32 h_outstream)
846{
847 struct hpi_message hm;
848 struct hpi_response hr;
849 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
850 HPI_OSTREAM_SINEGEN);
851 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
852
853 hpi_send_recv(&hm, &hr);
854
855 return hr.error;
856}
857
858u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
859{
860 struct hpi_message hm;
861 struct hpi_response hr;
862 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
863 HPI_OSTREAM_RESET);
864 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
865
866 hpi_send_recv(&hm, &hr);
867
868 return hr.error;
869}
870
871u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys,
872 u32 h_outstream, struct hpi_format *p_format)
873{
874 struct hpi_message hm;
875 struct hpi_response hr;
876
877 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
878 HPI_OSTREAM_QUERY_FORMAT);
879 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
880
881 hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
882
883 hpi_send_recv(&hm, &hr);
884
885 return hr.error;
886}
887
888u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys,
889 u32 h_outstream, struct hpi_format *p_format)
890{
891 struct hpi_message hm;
892 struct hpi_response hr;
893
894 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
895 HPI_OSTREAM_SET_FORMAT);
896 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
897
898 hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
899
900 hpi_send_recv(&hm, &hr);
901
902 return hr.error;
903}
904
905u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys,
906 u32 h_outstream, short velocity)
907{
908 struct hpi_message hm;
909 struct hpi_response hr;
910
911 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
912 HPI_OSTREAM_SET_VELOCITY);
913 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
914 hm.u.d.u.velocity = velocity;
915
916 hpi_send_recv(&hm, &hr);
917
918 return hr.error;
919}
920
921u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys,
922 u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample)
923{
924 struct hpi_message hm;
925 struct hpi_response hr;
926
927 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
928 HPI_OSTREAM_SET_PUNCHINOUT);
929 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
930
931 hm.u.d.u.pio.punch_in_sample = punch_in_sample;
932 hm.u.d.u.pio.punch_out_sample = punch_out_sample;
933
934 hpi_send_recv(&hm, &hr);
935
936 return hr.error;
937}
938
939u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
940 u32 h_outstream, u16 mode)
941{
942 struct hpi_message hm;
943 struct hpi_response hr;
944
945 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
946 HPI_OSTREAM_ANC_RESET);
947 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
948 hm.u.d.u.data.format.channels = mode;
949 hpi_send_recv(&hm, &hr);
950 return hr.error;
951}
952
953u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
954 u32 h_outstream, u32 *pframes_available)
955{
956 struct hpi_message hm;
957 struct hpi_response hr;
958
959 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
960 HPI_OSTREAM_ANC_GET_INFO);
961 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
962 hpi_send_recv(&hm, &hr);
963 if (hr.error == 0) {
964 if (pframes_available)
965 *pframes_available =
966 hr.u.d.u.stream_info.data_available /
967 sizeof(struct hpi_anc_frame);
968 }
969 return hr.error;
970}
971
972u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
973 u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer,
974 u32 anc_frame_buffer_size_in_bytes,
975 u32 number_of_ancillary_frames_to_read)
976{
977 struct hpi_message hm;
978 struct hpi_response hr;
979 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
980 HPI_OSTREAM_ANC_READ);
981 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
982 hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer;
983 hm.u.d.u.data.data_size =
984 number_of_ancillary_frames_to_read *
985 sizeof(struct hpi_anc_frame);
986 if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes)
987 hpi_send_recv(&hm, &hr);
988 else
989 hr.error = HPI_ERROR_INVALID_DATA_TRANSFER;
990 return hr.error;
991}
992
993u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys,
994 u32 h_outstream, u32 time_scale)
995{
996 struct hpi_message hm;
997 struct hpi_response hr;
998
999 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1000 HPI_OSTREAM_SET_TIMESCALE);
1001 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1002
1003 hm.u.d.u.time_scale = time_scale;
1004
1005 hpi_send_recv(&hm, &hr);
1006
1007 return hr.error;
1008}
1009
1010u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
1011 u32 h_outstream, u32 size_in_bytes)
1012{
1013 struct hpi_message hm;
1014 struct hpi_response hr;
1015
1016 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1017 HPI_OSTREAM_HOSTBUFFER_ALLOC);
1018 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1019 hm.u.d.u.data.data_size = size_in_bytes;
1020 hpi_send_recv(&hm, &hr);
1021 return hr.error;
1022}
1023
1024u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
1025 u32 h_outstream, u8 **pp_buffer,
1026 struct hpi_hostbuffer_status **pp_status)
1027{
1028 struct hpi_message hm;
1029 struct hpi_response hr;
1030
1031 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1032 HPI_OSTREAM_HOSTBUFFER_GET_INFO);
1033 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1034 hpi_send_recv(&hm, &hr);
1035
1036 if (hr.error == 0) {
1037 if (pp_buffer)
1038 *pp_buffer = hr.u.d.u.hostbuffer_info.p_buffer;
1039 if (pp_status)
1040 *pp_status = hr.u.d.u.hostbuffer_info.p_status;
1041 }
1042 return hr.error;
1043}
1044
1045u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
1046 u32 h_outstream)
1047{
1048 struct hpi_message hm;
1049 struct hpi_response hr;
1050
1051 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1052 HPI_OSTREAM_HOSTBUFFER_FREE);
1053 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1054 hpi_send_recv(&hm, &hr);
1055 return hr.error;
1056}
1057
1058u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
1059 u32 h_outstream, u32 h_stream)
1060{
1061 struct hpi_message hm;
1062 struct hpi_response hr;
1063 u16 adapter;
1064 char c_obj_type;
1065
1066 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1067 HPI_OSTREAM_GROUP_ADD);
1068 hr.error = 0;
1069 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1070 c_obj_type = hpi_handle_object(h_stream);
1071 switch (c_obj_type) {
1072 case HPI_OBJ_OSTREAM:
1073 hm.u.d.u.stream.object_type = HPI_OBJ_OSTREAM;
1074 u32TOINDEXES(h_stream, &adapter,
1075 &hm.u.d.u.stream.stream_index);
1076 break;
1077 case HPI_OBJ_ISTREAM:
1078 hm.u.d.u.stream.object_type = HPI_OBJ_ISTREAM;
1079 u32TOINDEXES(h_stream, &adapter,
1080 &hm.u.d.u.stream.stream_index);
1081 break;
1082 default:
1083 return HPI_ERROR_INVALID_STREAM;
1084 }
1085 if (adapter != hm.adapter_index)
1086 return HPI_ERROR_NO_INTERADAPTER_GROUPS;
1087
1088 hpi_send_recv(&hm, &hr);
1089 return hr.error;
1090}
1091
1092u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys,
1093 u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map)
1094{
1095 struct hpi_message hm;
1096 struct hpi_response hr;
1097
1098 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1099 HPI_OSTREAM_GROUP_GETMAP);
1100 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1101 hpi_send_recv(&hm, &hr);
1102
1103 if (poutstream_map)
1104 *poutstream_map = hr.u.d.u.group_info.outstream_group_map;
1105 if (pinstream_map)
1106 *pinstream_map = hr.u.d.u.group_info.instream_group_map;
1107
1108 return hr.error;
1109}
1110
1111u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys,
1112 u32 h_outstream)
1113{
1114 struct hpi_message hm;
1115 struct hpi_response hr;
1116
1117 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
1118 HPI_OSTREAM_GROUP_RESET);
1119 u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
1120 hpi_send_recv(&hm, &hr);
1121 return hr.error;
1122}
1123
1124u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1125 u16 instream_index, u32 *ph_instream)
1126{
1127 struct hpi_message hm;
1128 struct hpi_response hr;
1129
1130 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1131 HPI_ISTREAM_OPEN);
1132 hm.adapter_index = adapter_index;
1133 hm.obj_index = instream_index;
1134
1135 hpi_send_recv(&hm, &hr);
1136
1137 if (hr.error == 0)
1138 *ph_instream =
1139 hpi_indexes_to_handle(HPI_OBJ_ISTREAM, adapter_index,
1140 instream_index);
1141 else
1142 *ph_instream = 0;
1143
1144 return hr.error;
1145}
1146
1147u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
1148{
1149 struct hpi_message hm;
1150 struct hpi_response hr;
1151
1152 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1153 HPI_ISTREAM_HOSTBUFFER_FREE);
1154 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1155 hpi_send_recv(&hm, &hr);
1156
1157 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1158 HPI_ISTREAM_GROUP_RESET);
1159 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1160 hpi_send_recv(&hm, &hr);
1161
1162 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1163 HPI_ISTREAM_CLOSE);
1164 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1165 hpi_send_recv(&hm, &hr);
1166
1167 return hr.error;
1168}
1169
1170u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys,
1171 u32 h_instream, const struct hpi_format *p_format)
1172{
1173 struct hpi_message hm;
1174 struct hpi_response hr;
1175
1176 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1177 HPI_ISTREAM_QUERY_FORMAT);
1178 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1179 hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
1180
1181 hpi_send_recv(&hm, &hr);
1182
1183 return hr.error;
1184}
1185
1186u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys,
1187 u32 h_instream, const struct hpi_format *p_format)
1188{
1189 struct hpi_message hm;
1190 struct hpi_response hr;
1191
1192 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1193 HPI_ISTREAM_SET_FORMAT);
1194 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1195 hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
1196
1197 hpi_send_recv(&hm, &hr);
1198
1199 return hr.error;
1200}
1201
1202u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream,
1203 u8 *pb_data, u32 bytes_to_read)
1204{
1205 struct hpi_message hm;
1206 struct hpi_response hr;
1207
1208 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1209 HPI_ISTREAM_READ);
1210 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1211 hm.u.d.u.data.data_size = bytes_to_read;
1212 hm.u.d.u.data.pb_data = pb_data;
1213
1214 hpi_send_recv(&hm, &hr);
1215
1216 return hr.error;
1217}
1218
1219u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
1220{
1221 struct hpi_message hm;
1222 struct hpi_response hr;
1223
1224 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1225 HPI_ISTREAM_START);
1226 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1227
1228 hpi_send_recv(&hm, &hr);
1229
1230 return hr.error;
1231}
1232
1233u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys,
1234 u32 h_instream)
1235{
1236 struct hpi_message hm;
1237 struct hpi_response hr;
1238
1239 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1240 HPI_ISTREAM_WAIT_START);
1241 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1242
1243 hpi_send_recv(&hm, &hr);
1244
1245 return hr.error;
1246}
1247
1248u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
1249{
1250 struct hpi_message hm;
1251 struct hpi_response hr;
1252
1253 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1254 HPI_ISTREAM_STOP);
1255 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1256
1257 hpi_send_recv(&hm, &hr);
1258
1259 return hr.error;
1260}
1261
1262u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
1263{
1264 struct hpi_message hm;
1265 struct hpi_response hr;
1266
1267 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1268 HPI_ISTREAM_RESET);
1269 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1270
1271 hpi_send_recv(&hm, &hr);
1272
1273 return hr.error;
1274}
1275
1276u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
1277 u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded,
1278 u32 *psamples_recorded, u32 *pauxiliary_data_recorded)
1279{
1280 struct hpi_message hm;
1281 struct hpi_response hr;
1282 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1283 HPI_ISTREAM_GET_INFO);
1284 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1285
1286 hpi_send_recv(&hm, &hr);
1287
1288 if (pw_state)
1289 *pw_state = hr.u.d.u.stream_info.state;
1290 if (pbuffer_size)
1291 *pbuffer_size = hr.u.d.u.stream_info.buffer_size;
1292 if (pdata_recorded)
1293 *pdata_recorded = hr.u.d.u.stream_info.data_available;
1294 if (psamples_recorded)
1295 *psamples_recorded = hr.u.d.u.stream_info.samples_transferred;
1296 if (pauxiliary_data_recorded)
1297 *pauxiliary_data_recorded =
1298 hr.u.d.u.stream_info.auxiliary_data_available;
1299 return hr.error;
1300}
1301
1302u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
1303 u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment,
1304 u16 idle_bit)
1305{
1306 struct hpi_message hm;
1307 struct hpi_response hr;
1308 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1309 HPI_ISTREAM_ANC_RESET);
1310 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1311 hm.u.d.u.data.format.attributes = bytes_per_frame;
1312 hm.u.d.u.data.format.format = (mode << 8) | (alignment & 0xff);
1313 hm.u.d.u.data.format.channels = idle_bit;
1314 hpi_send_recv(&hm, &hr);
1315 return hr.error;
1316}
1317
1318u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
1319 u32 h_instream, u32 *pframe_space)
1320{
1321 struct hpi_message hm;
1322 struct hpi_response hr;
1323 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1324 HPI_ISTREAM_ANC_GET_INFO);
1325 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1326 hpi_send_recv(&hm, &hr);
1327 if (pframe_space)
1328 *pframe_space =
1329 (hr.u.d.u.stream_info.buffer_size -
1330 hr.u.d.u.stream_info.data_available) /
1331 sizeof(struct hpi_anc_frame);
1332 return hr.error;
1333}
1334
1335u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
1336 u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer,
1337 u32 anc_frame_buffer_size_in_bytes,
1338 u32 number_of_ancillary_frames_to_write)
1339{
1340 struct hpi_message hm;
1341 struct hpi_response hr;
1342
1343 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1344 HPI_ISTREAM_ANC_WRITE);
1345 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1346 hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer;
1347 hm.u.d.u.data.data_size =
1348 number_of_ancillary_frames_to_write *
1349 sizeof(struct hpi_anc_frame);
1350 if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes)
1351 hpi_send_recv(&hm, &hr);
1352 else
1353 hr.error = HPI_ERROR_INVALID_DATA_TRANSFER;
1354 return hr.error;
1355}
1356
1357u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
1358 u32 h_instream, u32 size_in_bytes)
1359{
1360
1361 struct hpi_message hm;
1362 struct hpi_response hr;
1363
1364 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1365 HPI_ISTREAM_HOSTBUFFER_ALLOC);
1366 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1367 hm.u.d.u.data.data_size = size_in_bytes;
1368 hpi_send_recv(&hm, &hr);
1369 return hr.error;
1370}
1371
1372u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
1373 u32 h_instream, u8 **pp_buffer,
1374 struct hpi_hostbuffer_status **pp_status)
1375{
1376 struct hpi_message hm;
1377 struct hpi_response hr;
1378
1379 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1380 HPI_ISTREAM_HOSTBUFFER_GET_INFO);
1381 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1382 hpi_send_recv(&hm, &hr);
1383
1384 if (hr.error == 0) {
1385 if (pp_buffer)
1386 *pp_buffer = hr.u.d.u.hostbuffer_info.p_buffer;
1387 if (pp_status)
1388 *pp_status = hr.u.d.u.hostbuffer_info.p_status;
1389 }
1390 return hr.error;
1391}
1392
1393u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
1394 u32 h_instream)
1395{
1396
1397 struct hpi_message hm;
1398 struct hpi_response hr;
1399
1400 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1401 HPI_ISTREAM_HOSTBUFFER_FREE);
1402 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1403 hpi_send_recv(&hm, &hr);
1404 return hr.error;
1405}
1406
1407u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
1408 u32 h_instream, u32 h_stream)
1409{
1410 struct hpi_message hm;
1411 struct hpi_response hr;
1412 u16 adapter;
1413 char c_obj_type;
1414
1415 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1416 HPI_ISTREAM_GROUP_ADD);
1417 hr.error = 0;
1418 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1419 c_obj_type = hpi_handle_object(h_stream);
1420
1421 switch (c_obj_type) {
1422 case HPI_OBJ_OSTREAM:
1423 hm.u.d.u.stream.object_type = HPI_OBJ_OSTREAM;
1424 u32TOINDEXES(h_stream, &adapter,
1425 &hm.u.d.u.stream.stream_index);
1426 break;
1427 case HPI_OBJ_ISTREAM:
1428 hm.u.d.u.stream.object_type = HPI_OBJ_ISTREAM;
1429 u32TOINDEXES(h_stream, &adapter,
1430 &hm.u.d.u.stream.stream_index);
1431 break;
1432 default:
1433 return HPI_ERROR_INVALID_STREAM;
1434 }
1435
1436 if (adapter != hm.adapter_index)
1437 return HPI_ERROR_NO_INTERADAPTER_GROUPS;
1438
1439 hpi_send_recv(&hm, &hr);
1440 return hr.error;
1441}
1442
1443u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys,
1444 u32 h_instream, u32 *poutstream_map, u32 *pinstream_map)
1445{
1446 struct hpi_message hm;
1447 struct hpi_response hr;
1448
1449 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1450 HPI_ISTREAM_HOSTBUFFER_FREE);
1451 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1452 hpi_send_recv(&hm, &hr);
1453
1454 if (poutstream_map)
1455 *poutstream_map = hr.u.d.u.group_info.outstream_group_map;
1456 if (pinstream_map)
1457 *pinstream_map = hr.u.d.u.group_info.instream_group_map;
1458
1459 return hr.error;
1460}
1461
1462u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys,
1463 u32 h_instream)
1464{
1465 struct hpi_message hm;
1466 struct hpi_response hr;
1467
1468 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
1469 HPI_ISTREAM_GROUP_RESET);
1470 u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
1471 hpi_send_recv(&hm, &hr);
1472 return hr.error;
1473}
1474
1475u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
1476 u32 *ph_mixer)
1477{
1478 struct hpi_message hm;
1479 struct hpi_response hr;
1480 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
1481 hm.adapter_index = adapter_index;
1482
1483 hpi_send_recv(&hm, &hr);
1484
1485 if (hr.error == 0)
1486 *ph_mixer =
1487 hpi_indexes_to_handle(HPI_OBJ_MIXER, adapter_index,
1488 0);
1489 else
1490 *ph_mixer = 0;
1491 return hr.error;
1492}
1493
1494u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer)
1495{
1496 struct hpi_message hm;
1497 struct hpi_response hr;
1498 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE);
1499 u32TOINDEX(h_mixer, &hm.adapter_index);
1500 hpi_send_recv(&hm, &hr);
1501 return hr.error;
1502}
1503
1504u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
1505 u16 src_node_type, u16 src_node_type_index, u16 dst_node_type,
1506 u16 dst_node_type_index, u16 control_type, u32 *ph_control)
1507{
1508 struct hpi_message hm;
1509 struct hpi_response hr;
1510 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER,
1511 HPI_MIXER_GET_CONTROL);
1512 u32TOINDEX(h_mixer, &hm.adapter_index);
1513 hm.u.m.node_type1 = src_node_type;
1514 hm.u.m.node_index1 = src_node_type_index;
1515 hm.u.m.node_type2 = dst_node_type;
1516 hm.u.m.node_index2 = dst_node_type_index;
1517 hm.u.m.control_type = control_type;
1518
1519 hpi_send_recv(&hm, &hr);
1520
1521 if (hr.error == 0)
1522 *ph_control =
1523 hpi_indexes_to_handle(HPI_OBJ_CONTROL,
1524 hm.adapter_index, hr.u.m.control_index);
1525 else
1526 *ph_control = 0;
1527 return hr.error;
1528}
1529
1530u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys,
1531 u32 h_mixer, u16 control_index, u16 *pw_src_node_type,
1532 u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index,
1533 u16 *pw_control_type, u32 *ph_control)
1534{
1535 struct hpi_message hm;
1536 struct hpi_response hr;
1537 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER,
1538 HPI_MIXER_GET_CONTROL_BY_INDEX);
1539 u32TOINDEX(h_mixer, &hm.adapter_index);
1540 hm.u.m.control_index = control_index;
1541 hpi_send_recv(&hm, &hr);
1542
1543 if (pw_src_node_type) {
1544 *pw_src_node_type =
1545 hr.u.m.src_node_type + HPI_SOURCENODE_NONE;
1546 *pw_src_node_index = hr.u.m.src_node_index;
1547 *pw_dst_node_type = hr.u.m.dst_node_type + HPI_DESTNODE_NONE;
1548 *pw_dst_node_index = hr.u.m.dst_node_index;
1549 }
1550 if (pw_control_type)
1551 *pw_control_type = hr.u.m.control_index;
1552
1553 if (ph_control) {
1554 if (hr.error == 0)
1555 *ph_control =
1556 hpi_indexes_to_handle(HPI_OBJ_CONTROL,
1557 hm.adapter_index, control_index);
1558 else
1559 *ph_control = 0;
1560 }
1561 return hr.error;
1562}
1563
1564u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
1565 enum HPI_MIXER_STORE_COMMAND command, u16 index)
1566{
1567 struct hpi_message hm;
1568 struct hpi_response hr;
1569 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_STORE);
1570 u32TOINDEX(h_mixer, &hm.adapter_index);
1571 hm.u.mx.store.command = command;
1572 hm.u.mx.store.index = index;
1573 hpi_send_recv(&hm, &hr);
1574 return hr.error;
1575}
1576
1577static
1578u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
1579 const u32 h_control, const u16 attrib, const u32 param1,
1580 const u32 param2)
1581{
1582 struct hpi_message hm;
1583 struct hpi_response hr;
1584 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1585 HPI_CONTROL_SET_STATE);
1586 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1587 hm.u.c.attribute = attrib;
1588 hm.u.c.param1 = param1;
1589 hm.u.c.param2 = param2;
1590 hpi_send_recv(&hm, &hr);
1591 return hr.error;
1592}
1593
1594static
1595u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
1596 const u32 h_control, const u16 attrib, u32 param1, u32 param2,
1597 u32 *pparam1, u32 *pparam2)
1598{
1599 struct hpi_message hm;
1600 struct hpi_response hr;
1601 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1602 HPI_CONTROL_GET_STATE);
1603 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1604 hm.u.c.attribute = attrib;
1605 hm.u.c.param1 = param1;
1606 hm.u.c.param2 = param2;
1607 hpi_send_recv(&hm, &hr);
1608 if (pparam1)
1609 *pparam1 = hr.u.c.param1;
1610 if (pparam2)
1611 *pparam2 = hr.u.c.param2;
1612
1613 return hr.error;
1614}
1615
1616#define hpi_control_param1_get(s, h, a, p1) \
1617 hpi_control_param_get(s, h, a, 0, 0, p1, NULL)
1618#define hpi_control_param2_get(s, h, a, p1, p2) \
1619 hpi_control_param_get(s, h, a, 0, 0, p1, p2)
1620#define hpi_control_ex_param1_get(s, h, a, p1) \
1621 hpi_control_ex_param_get(s, h, a, 0, 0, p1, NULL)
1622#define hpi_control_ex_param2_get(s, h, a, p1, p2) \
1623 hpi_control_ex_param_get(s, h, a, 0, 0, p1, p2)
1624
1625static
1626u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
1627 const u32 h_control, const u16 attrib, const u32 index,
1628 const u32 param, u32 *psetting)
1629{
1630 struct hpi_message hm;
1631 struct hpi_response hr;
1632 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1633 HPI_CONTROL_GET_INFO);
1634 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1635
1636 hm.u.c.attribute = attrib;
1637 hm.u.c.param1 = index;
1638 hm.u.c.param2 = param;
1639
1640 hpi_send_recv(&hm, &hr);
1641 *psetting = hr.u.c.param1;
1642
1643 return hr.error;
1644}
1645
1646static u16 hpi_control_get_string(const struct hpi_hsubsys *ph_subsys,
1647 const u32 h_control, const u16 attribute, char *psz_string,
1648 const u32 string_length)
1649{
1650 unsigned int sub_string_index = 0, j = 0;
1651 char c = 0;
1652 unsigned int n = 0;
1653 u16 hE = 0;
1654
1655 if ((string_length < 1) || (string_length > 256))
1656 return HPI_ERROR_INVALID_CONTROL_VALUE;
1657 for (sub_string_index = 0; sub_string_index < string_length;
1658 sub_string_index += 8) {
1659 struct hpi_message hm;
1660 struct hpi_response hr;
1661
1662 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1663 HPI_CONTROL_GET_STATE);
1664 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1665 hm.u.c.attribute = attribute;
1666 hm.u.c.param1 = sub_string_index;
1667 hm.u.c.param2 = 0;
1668 hpi_send_recv(&hm, &hr);
1669
1670 if (sub_string_index == 0
1671 && (hr.u.cu.chars8.remaining_chars + 8) >
1672 string_length)
1673 return HPI_ERROR_INVALID_CONTROL_VALUE;
1674
1675 if (hr.error) {
1676 hE = hr.error;
1677 break;
1678 }
1679 for (j = 0; j < 8; j++) {
1680 c = hr.u.cu.chars8.sz_data[j];
1681 psz_string[sub_string_index + j] = c;
1682 n++;
1683 if (n >= string_length) {
1684 psz_string[string_length - 1] = 0;
1685 hE = HPI_ERROR_INVALID_CONTROL_VALUE;
1686 break;
1687 }
1688 if (c == 0)
1689 break;
1690 }
1691
1692 if ((hr.u.cu.chars8.remaining_chars == 0)
1693 && ((sub_string_index + j) < string_length)
1694 && (c != 0)) {
1695 c = 0;
1696 psz_string[sub_string_index + j] = c;
1697 }
1698 if (c == 0)
1699 break;
1700 }
1701 return hE;
1702}
1703
1704u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys,
1705 const u32 h_aes_rx, const u32 index, u16 *pw_format)
1706{
1707 u32 qr;
1708 u16 err;
1709
1710 err = hpi_control_query(ph_subsys, h_aes_rx, HPI_AESEBURX_FORMAT,
1711 index, 0, &qr);
1712 *pw_format = (u16)qr;
1713 return err;
1714}
1715
1716u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys,
1717 u32 h_control, u16 format)
1718{
1719 return hpi_control_param_set(ph_subsys, h_control,
1720 HPI_AESEBURX_FORMAT, format, 0);
1721}
1722
1723u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys,
1724 u32 h_control, u16 *pw_format)
1725{
1726 u16 err;
1727 u32 param;
1728
1729 err = hpi_control_param1_get(ph_subsys, h_control,
1730 HPI_AESEBURX_FORMAT, &param);
1731 if (!err && pw_format)
1732 *pw_format = (u16)param;
1733
1734 return err;
1735}
1736
1737u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
1738 u32 h_control, u32 *psample_rate)
1739{
1740 return hpi_control_param1_get(ph_subsys, h_control,
1741 HPI_AESEBURX_SAMPLERATE, psample_rate);
1742}
1743
1744u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys,
1745 u32 h_control, u16 index, u16 *pw_data)
1746{
1747 struct hpi_message hm;
1748 struct hpi_response hr;
1749 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1750 HPI_CONTROL_GET_STATE);
1751 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1752 hm.u.c.attribute = HPI_AESEBURX_USERDATA;
1753 hm.u.c.param1 = index;
1754
1755 hpi_send_recv(&hm, &hr);
1756
1757 if (pw_data)
1758 *pw_data = (u16)hr.u.c.param2;
1759 return hr.error;
1760}
1761
1762u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys
1763 *ph_subsys, u32 h_control, u16 index, u16 *pw_data)
1764{
1765 struct hpi_message hm;
1766 struct hpi_response hr;
1767 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1768 HPI_CONTROL_GET_STATE);
1769 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1770 hm.u.c.attribute = HPI_AESEBURX_CHANNELSTATUS;
1771 hm.u.c.param1 = index;
1772
1773 hpi_send_recv(&hm, &hr);
1774
1775 if (pw_data)
1776 *pw_data = (u16)hr.u.c.param2;
1777 return hr.error;
1778}
1779
1780u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys,
1781 u32 h_control, u16 *pw_error_data)
1782{
1783 u32 error_data = 0;
1784 u16 error = 0;
1785
1786 error = hpi_control_param1_get(ph_subsys, h_control,
1787 HPI_AESEBURX_ERRORSTATUS, &error_data);
1788 if (pw_error_data)
1789 *pw_error_data = (u16)error_data;
1790 return error;
1791}
1792
1793u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys
1794 *ph_subsys, u32 h_control, u32 sample_rate)
1795{
1796 return hpi_control_param_set(ph_subsys, h_control,
1797 HPI_AESEBUTX_SAMPLERATE, sample_rate, 0);
1798}
1799
1800u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys,
1801 u32 h_control, u16 index, u16 data)
1802{
1803 return hpi_control_param_set(ph_subsys, h_control,
1804 HPI_AESEBUTX_USERDATA, index, data);
1805}
1806
1807u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys
1808 *ph_subsys, u32 h_control, u16 index, u16 data)
1809{
1810 return hpi_control_param_set(ph_subsys, h_control,
1811 HPI_AESEBUTX_CHANNELSTATUS, index, data);
1812}
1813
1814u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys
1815 *ph_subsys, u32 h_control, u16 index, u16 *pw_data)
1816{
1817 return HPI_ERROR_INVALID_OPERATION;
1818}
1819
1820u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys,
1821 const u32 h_aes_tx, const u32 index, u16 *pw_format)
1822{
1823 u32 qr;
1824 u16 err;
1825
1826 err = hpi_control_query(ph_subsys, h_aes_tx, HPI_AESEBUTX_FORMAT,
1827 index, 0, &qr);
1828 *pw_format = (u16)qr;
1829 return err;
1830}
1831
1832u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys,
1833 u32 h_control, u16 output_format)
1834{
1835 return hpi_control_param_set(ph_subsys, h_control,
1836 HPI_AESEBUTX_FORMAT, output_format, 0);
1837}
1838
1839u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys,
1840 u32 h_control, u16 *pw_output_format)
1841{
1842 u16 err;
1843 u32 param;
1844
1845 err = hpi_control_param1_get(ph_subsys, h_control,
1846 HPI_AESEBUTX_FORMAT, &param);
1847 if (!err && pw_output_format)
1848 *pw_output_format = (u16)param;
1849
1850 return err;
1851}
1852
1853u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys,
1854 u32 h_control, u16 edge_type)
1855{
1856 return hpi_control_param_set(ph_subsys, h_control,
1857 HPI_BITSTREAM_CLOCK_EDGE, edge_type, 0);
1858}
1859
1860u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys,
1861 u32 h_control, u16 polarity)
1862{
1863 return hpi_control_param_set(ph_subsys, h_control,
1864 HPI_BITSTREAM_DATA_POLARITY, polarity, 0);
1865}
1866
1867u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys,
1868 u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity)
1869{
1870 struct hpi_message hm;
1871 struct hpi_response hr;
1872 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
1873 HPI_CONTROL_GET_STATE);
1874 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1875 hm.u.c.attribute = HPI_BITSTREAM_ACTIVITY;
1876 hpi_send_recv(&hm, &hr);
1877 if (pw_clk_activity)
1878 *pw_clk_activity = (u16)hr.u.c.param1;
1879 if (pw_data_activity)
1880 *pw_data_activity = (u16)hr.u.c.param2;
1881 return hr.error;
1882}
1883
1884u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys,
1885 const u32 h_mode, const u32 index, u16 *pw_mode)
1886{
1887 u32 qr;
1888 u16 err;
1889
1890 err = hpi_control_query(ph_subsys, h_mode, HPI_CHANNEL_MODE_MODE,
1891 index, 0, &qr);
1892 *pw_mode = (u16)qr;
1893 return err;
1894}
1895
1896u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1897 u16 mode)
1898{
1899 return hpi_control_param_set(ph_subsys, h_control,
1900 HPI_CHANNEL_MODE_MODE, mode, 0);
1901}
1902
1903u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1904 u16 *mode)
1905{
1906 u32 mode32 = 0;
1907 u16 error = hpi_control_param1_get(ph_subsys, h_control,
1908 HPI_CHANNEL_MODE_MODE, &mode32);
1909 if (mode)
1910 *mode = (u16)mode32;
1911 return error;
1912}
1913
1914u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1915 u32 hmi_address, u32 byte_count, u8 *pb_data)
1916{
1917 struct hpi_message hm;
1918 struct hpi_response hr;
1919 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
1920 HPI_CONTROL_SET_STATE);
1921 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1922
1923 hm.u.cx.u.cobranet_data.byte_count = byte_count;
1924 hm.u.cx.u.cobranet_data.hmi_address = hmi_address;
1925
1926 if (byte_count <= 8) {
1927 memcpy(hm.u.cx.u.cobranet_data.data, pb_data, byte_count);
1928 hm.u.cx.attribute = HPI_COBRANET_SET;
1929 } else {
1930 hm.u.cx.u.cobranet_bigdata.pb_data = pb_data;
1931 hm.u.cx.attribute = HPI_COBRANET_SET_DATA;
1932 }
1933
1934 hpi_send_recv(&hm, &hr);
1935
1936 return hr.error;
1937}
1938
1939u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
1940 u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data)
1941{
1942 struct hpi_message hm;
1943 struct hpi_response hr;
1944 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
1945 HPI_CONTROL_GET_STATE);
1946 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1947
1948 hm.u.cx.u.cobranet_data.byte_count = max_byte_count;
1949 hm.u.cx.u.cobranet_data.hmi_address = hmi_address;
1950
1951 if (max_byte_count <= 8) {
1952 hm.u.cx.attribute = HPI_COBRANET_GET;
1953 } else {
1954 hm.u.cx.u.cobranet_bigdata.pb_data = pb_data;
1955 hm.u.cx.attribute = HPI_COBRANET_GET_DATA;
1956 }
1957
1958 hpi_send_recv(&hm, &hr);
1959 if (!hr.error && pb_data) {
1960
1961 *pbyte_count = hr.u.cx.u.cobranet_data.byte_count;
1962
1963 if (*pbyte_count < max_byte_count)
1964 max_byte_count = *pbyte_count;
1965
1966 if (hm.u.cx.attribute == HPI_COBRANET_GET) {
1967 memcpy(pb_data, hr.u.cx.u.cobranet_data.data,
1968 max_byte_count);
1969 } else {
1970
1971 }
1972
1973 }
1974 return hr.error;
1975}
1976
1977u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
1978 u32 h_control, u32 *pstatus, u32 *preadable_size,
1979 u32 *pwriteable_size)
1980{
1981 struct hpi_message hm;
1982 struct hpi_response hr;
1983 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
1984 HPI_CONTROL_GET_STATE);
1985 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
1986
1987 hm.u.cx.attribute = HPI_COBRANET_GET_STATUS;
1988
1989 hpi_send_recv(&hm, &hr);
1990 if (!hr.error) {
1991 if (pstatus)
1992 *pstatus = hr.u.cx.u.cobranet_status.status;
1993 if (preadable_size)
1994 *preadable_size =
1995 hr.u.cx.u.cobranet_status.readable_size;
1996 if (pwriteable_size)
1997 *pwriteable_size =
1998 hr.u.cx.u.cobranet_status.writeable_size;
1999 }
2000 return hr.error;
2001}
2002
2003u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
2004 u32 h_control, u32 *pi_paddress)
2005{
2006 u32 byte_count;
2007 u32 iP;
2008 u16 error;
2009 error = hpi_cobranet_hmi_read(ph_subsys, h_control,
2010 HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count,
2011 (u8 *)&iP);
2012
2013 *pi_paddress =
2014 ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP &
2015 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8);
2016
2017 if (error)
2018 *pi_paddress = 0;
2019
2020 return error;
2021
2022}
2023
2024u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys,
2025 u32 h_control, u32 i_paddress)
2026{
2027 u32 iP;
2028 u16 error;
2029
2030 iP = ((i_paddress & 0xff000000) >> 8) | ((i_paddress & 0x00ff0000) <<
2031 8) | ((i_paddress & 0x0000ff00) >> 8) | ((i_paddress &
2032 0x000000ff) << 8);
2033
2034 error = hpi_cobranet_hmi_write(ph_subsys, h_control,
2035 HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, (u8 *)&iP);
2036
2037 return error;
2038
2039}
2040
2041u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
2042 u32 h_control, u32 *pi_paddress)
2043{
2044 u32 byte_count;
2045 u32 iP;
2046 u16 error;
2047 error = hpi_cobranet_hmi_read(ph_subsys, h_control,
2048 HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, &byte_count,
2049 (u8 *)&iP);
2050
2051 *pi_paddress =
2052 ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP &
2053 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8);
2054
2055 if (error)
2056 *pi_paddress = 0;
2057
2058 return error;
2059
2060}
2061
2062u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
2063 u32 h_control, u32 i_paddress)
2064{
2065 u32 iP;
2066 u16 error;
2067
2068 iP = ((i_paddress & 0xff000000) >> 8) | ((i_paddress & 0x00ff0000) <<
2069 8) | ((i_paddress & 0x0000ff00) >> 8) | ((i_paddress &
2070 0x000000ff) << 8);
2071
2072 error = hpi_cobranet_hmi_write(ph_subsys, h_control,
2073 HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, (u8 *)&iP);
2074
2075 return error;
2076
2077}
2078
2079u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
2080 u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs)
2081{
2082 u32 byte_count;
2083 u16 error;
2084 u32 mAC;
2085 error = hpi_cobranet_hmi_read(ph_subsys, h_control,
2086 HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count,
2087 (u8 *)&mAC);
2088 *pmAC_MS_bs =
2089 ((mAC & 0xff000000) >> 8) | ((mAC & 0x00ff0000) << 8) | ((mAC
2090 & 0x0000ff00) >> 8) | ((mAC & 0x000000ff) << 8);
2091 error += hpi_cobranet_hmi_read(ph_subsys, h_control,
2092 HPI_COBRANET_HMI_cobra_if_phy_address + 1, 4, &byte_count,
2093 (u8 *)&mAC);
2094 *pmAC_LS_bs =
2095 ((mAC & 0xff000000) >> 8) | ((mAC & 0x00ff0000) << 8) | ((mAC
2096 & 0x0000ff00) >> 8) | ((mAC & 0x000000ff) << 8);
2097
2098 if (error) {
2099 *pmAC_MS_bs = 0;
2100 *pmAC_LS_bs = 0;
2101 }
2102
2103 return error;
2104}
2105
2106u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2107 u16 attack, u16 decay, short ratio100, short threshold0_01dB,
2108 short makeup_gain0_01dB)
2109{
2110 struct hpi_message hm;
2111 struct hpi_response hr;
2112 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2113 HPI_CONTROL_SET_STATE);
2114 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2115
2116 hm.u.c.param1 = attack + ((u32)ratio100 << 16);
2117 hm.u.c.param2 = (decay & 0xFFFFL);
2118 hm.u.c.an_log_value[0] = threshold0_01dB;
2119 hm.u.c.an_log_value[1] = makeup_gain0_01dB;
2120 hm.u.c.attribute = HPI_COMPANDER_PARAMS;
2121
2122 hpi_send_recv(&hm, &hr);
2123
2124 return hr.error;
2125}
2126
2127u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2128 u16 *pw_attack, u16 *pw_decay, short *pw_ratio100,
2129 short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB)
2130{
2131 struct hpi_message hm;
2132 struct hpi_response hr;
2133 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2134 HPI_CONTROL_GET_STATE);
2135 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2136 hm.u.c.attribute = HPI_COMPANDER_PARAMS;
2137
2138 hpi_send_recv(&hm, &hr);
2139
2140 if (pw_attack)
2141 *pw_attack = (short)(hr.u.c.param1 & 0xFFFF);
2142 if (pw_decay)
2143 *pw_decay = (short)(hr.u.c.param2 & 0xFFFF);
2144 if (pw_ratio100)
2145 *pw_ratio100 = (short)(hr.u.c.param1 >> 16);
2146
2147 if (pn_threshold0_01dB)
2148 *pn_threshold0_01dB = hr.u.c.an_log_value[0];
2149 if (pn_makeup_gain0_01dB)
2150 *pn_makeup_gain0_01dB = hr.u.c.an_log_value[1];
2151
2152 return hr.error;
2153}
2154
2155u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2156 short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB)
2157{
2158 struct hpi_message hm;
2159 struct hpi_response hr;
2160 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2161 HPI_CONTROL_GET_STATE);
2162 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2163 hm.u.c.attribute = HPI_LEVEL_RANGE;
2164
2165 hpi_send_recv(&hm, &hr);
2166 if (hr.error) {
2167 hr.u.c.an_log_value[0] = 0;
2168 hr.u.c.an_log_value[1] = 0;
2169 hr.u.c.param1 = 0;
2170 }
2171 if (min_gain_01dB)
2172 *min_gain_01dB = hr.u.c.an_log_value[0];
2173 if (max_gain_01dB)
2174 *max_gain_01dB = hr.u.c.an_log_value[1];
2175 if (step_gain_01dB)
2176 *step_gain_01dB = (short)hr.u.c.param1;
2177 return hr.error;
2178}
2179
2180u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2181 short an_gain0_01dB[HPI_MAX_CHANNELS]
2182 )
2183{
2184 struct hpi_message hm;
2185 struct hpi_response hr;
2186
2187 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2188 HPI_CONTROL_SET_STATE);
2189 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2190 memcpy(hm.u.c.an_log_value, an_gain0_01dB,
2191 sizeof(short) * HPI_MAX_CHANNELS);
2192 hm.u.c.attribute = HPI_LEVEL_GAIN;
2193
2194 hpi_send_recv(&hm, &hr);
2195
2196 return hr.error;
2197}
2198
2199u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2200 short an_gain0_01dB[HPI_MAX_CHANNELS]
2201 )
2202{
2203 struct hpi_message hm;
2204 struct hpi_response hr;
2205 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2206 HPI_CONTROL_GET_STATE);
2207 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2208 hm.u.c.attribute = HPI_LEVEL_GAIN;
2209
2210 hpi_send_recv(&hm, &hr);
2211
2212 memcpy(an_gain0_01dB, hr.u.c.an_log_value,
2213 sizeof(short) * HPI_MAX_CHANNELS);
2214 return hr.error;
2215}
2216
2217u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
2218 const u32 h_meter, u32 *p_channels)
2219{
2220 return hpi_control_query(ph_subsys, h_meter, HPI_METER_NUM_CHANNELS,
2221 0, 0, p_channels);
2222}
2223
2224u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2225 short an_peakdB[HPI_MAX_CHANNELS]
2226 )
2227{
2228 short i = 0;
2229
2230 struct hpi_message hm;
2231 struct hpi_response hr;
2232
2233 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2234 HPI_CONTROL_GET_STATE);
2235 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2236 hm.obj_index = hm.obj_index;
2237 hm.u.c.attribute = HPI_METER_PEAK;
2238
2239 hpi_send_recv(&hm, &hr);
2240
2241 if (!hr.error)
2242 memcpy(an_peakdB, hr.u.c.an_log_value,
2243 sizeof(short) * HPI_MAX_CHANNELS);
2244 else
2245 for (i = 0; i < HPI_MAX_CHANNELS; i++)
2246 an_peakdB[i] = HPI_METER_MINIMUM;
2247 return hr.error;
2248}
2249
2250u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2251 short an_rmsdB[HPI_MAX_CHANNELS]
2252 )
2253{
2254 short i = 0;
2255
2256 struct hpi_message hm;
2257 struct hpi_response hr;
2258
2259 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2260 HPI_CONTROL_GET_STATE);
2261 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2262 hm.u.c.attribute = HPI_METER_RMS;
2263
2264 hpi_send_recv(&hm, &hr);
2265
2266 if (!hr.error)
2267 memcpy(an_rmsdB, hr.u.c.an_log_value,
2268 sizeof(short) * HPI_MAX_CHANNELS);
2269 else
2270 for (i = 0; i < HPI_MAX_CHANNELS; i++)
2271 an_rmsdB[i] = HPI_METER_MINIMUM;
2272
2273 return hr.error;
2274}
2275
2276u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
2277 u32 h_control, u16 attack, u16 decay)
2278{
2279 return hpi_control_param_set(ph_subsys, h_control,
2280 HPI_METER_RMS_BALLISTICS, attack, decay);
2281}
2282
2283u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
2284 u32 h_control, u16 *pn_attack, u16 *pn_decay)
2285{
2286 u32 attack;
2287 u32 decay;
2288 u16 error;
2289
2290 error = hpi_control_param2_get(ph_subsys, h_control,
2291 HPI_METER_RMS_BALLISTICS, &attack, &decay);
2292
2293 if (pn_attack)
2294 *pn_attack = (unsigned short)attack;
2295 if (pn_decay)
2296 *pn_decay = (unsigned short)decay;
2297
2298 return error;
2299}
2300
2301u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
2302 u32 h_control, u16 attack, u16 decay)
2303{
2304 return hpi_control_param_set(ph_subsys, h_control,
2305 HPI_METER_PEAK_BALLISTICS, attack, decay);
2306}
2307
2308u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
2309 u32 h_control, u16 *pn_attack, u16 *pn_decay)
2310{
2311 u32 attack;
2312 u32 decay;
2313 u16 error;
2314
2315 error = hpi_control_param2_get(ph_subsys, h_control,
2316 HPI_METER_PEAK_BALLISTICS, &attack, &decay);
2317
2318 if (pn_attack)
2319 *pn_attack = (short)attack;
2320 if (pn_decay)
2321 *pn_decay = (short)decay;
2322
2323 return error;
2324}
2325
2326u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys,
2327 u32 h_control, u16 on_off)
2328{
2329 return hpi_control_param_set(ph_subsys, h_control,
2330 HPI_MICROPHONE_PHANTOM_POWER, (u32)on_off, 0);
2331}
2332
2333u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys,
2334 u32 h_control, u16 *pw_on_off)
2335{
2336 u16 error = 0;
2337 u32 on_off = 0;
2338 error = hpi_control_param1_get(ph_subsys, h_control,
2339 HPI_MICROPHONE_PHANTOM_POWER, &on_off);
2340 if (pw_on_off)
2341 *pw_on_off = (u16)on_off;
2342 return error;
2343}
2344
2345u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys,
2346 u32 h_control, u16 source_node_type, u16 source_node_index)
2347{
2348 return hpi_control_param_set(ph_subsys, h_control,
2349 HPI_MULTIPLEXER_SOURCE, source_node_type, source_node_index);
2350}
2351
2352u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys,
2353 u32 h_control, u16 *source_node_type, u16 *source_node_index)
2354{
2355 u32 node, index;
2356 u16 error = hpi_control_param2_get(ph_subsys, h_control,
2357 HPI_MULTIPLEXER_SOURCE, &node,
2358 &index);
2359 if (source_node_type)
2360 *source_node_type = (u16)node;
2361 if (source_node_index)
2362 *source_node_index = (u16)index;
2363 return error;
2364}
2365
2366u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys,
2367 u32 h_control, u16 index, u16 *source_node_type,
2368 u16 *source_node_index)
2369{
2370 struct hpi_message hm;
2371 struct hpi_response hr;
2372 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2373 HPI_CONTROL_GET_STATE);
2374 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2375 hm.u.c.attribute = HPI_MULTIPLEXER_QUERYSOURCE;
2376 hm.u.c.param1 = index;
2377
2378 hpi_send_recv(&hm, &hr);
2379
2380 if (source_node_type)
2381 *source_node_type = (u16)hr.u.c.param1;
2382 if (source_node_index)
2383 *source_node_index = (u16)hr.u.c.param2;
2384 return hr.error;
2385}
2386
2387u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys,
2388 u32 h_control, u16 *pw_number_of_bands, u16 *pw_on_off)
2389{
2390 u32 oB = 0;
2391 u32 oO = 0;
2392 u16 error = 0;
2393
2394 error = hpi_control_param2_get(ph_subsys, h_control,
2395 HPI_EQUALIZER_NUM_FILTERS, &oO, &oB);
2396 if (pw_number_of_bands)
2397 *pw_number_of_bands = (u16)oB;
2398 if (pw_on_off)
2399 *pw_on_off = (u16)oO;
2400 return error;
2401}
2402
2403u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys,
2404 u32 h_control, u16 on_off)
2405{
2406 return hpi_control_param_set(ph_subsys, h_control,
2407 HPI_EQUALIZER_NUM_FILTERS, on_off, 0);
2408}
2409
2410u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
2411 u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz,
2412 short *pnQ100, short *pn_gain0_01dB)
2413{
2414 struct hpi_message hm;
2415 struct hpi_response hr;
2416 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2417 HPI_CONTROL_GET_STATE);
2418 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2419 hm.u.c.attribute = HPI_EQUALIZER_FILTER;
2420 hm.u.c.param2 = index;
2421
2422 hpi_send_recv(&hm, &hr);
2423
2424 if (pfrequency_hz)
2425 *pfrequency_hz = hr.u.c.param1;
2426 if (pn_type)
2427 *pn_type = (u16)(hr.u.c.param2 >> 16);
2428 if (pnQ100)
2429 *pnQ100 = hr.u.c.an_log_value[1];
2430 if (pn_gain0_01dB)
2431 *pn_gain0_01dB = hr.u.c.an_log_value[0];
2432
2433 return hr.error;
2434}
2435
2436u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
2437 u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100,
2438 short gain0_01dB)
2439{
2440 struct hpi_message hm;
2441 struct hpi_response hr;
2442 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2443 HPI_CONTROL_SET_STATE);
2444 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2445
2446 hm.u.c.param1 = frequency_hz;
2447 hm.u.c.param2 = (index & 0xFFFFL) + ((u32)type << 16);
2448 hm.u.c.an_log_value[0] = gain0_01dB;
2449 hm.u.c.an_log_value[1] = q100;
2450 hm.u.c.attribute = HPI_EQUALIZER_FILTER;
2451
2452 hpi_send_recv(&hm, &hr);
2453
2454 return hr.error;
2455}
2456
2457u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
2458 u32 h_control, u16 index, short coeffs[5]
2459 )
2460{
2461 struct hpi_message hm;
2462 struct hpi_response hr;
2463 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2464 HPI_CONTROL_GET_STATE);
2465 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2466 hm.u.c.attribute = HPI_EQUALIZER_COEFFICIENTS;
2467 hm.u.c.param2 = index;
2468
2469 hpi_send_recv(&hm, &hr);
2470
2471 coeffs[0] = (short)hr.u.c.an_log_value[0];
2472 coeffs[1] = (short)hr.u.c.an_log_value[1];
2473 coeffs[2] = (short)hr.u.c.param1;
2474 coeffs[3] = (short)(hr.u.c.param1 >> 16);
2475 coeffs[4] = (short)hr.u.c.param2;
2476
2477 return hr.error;
2478}
2479
2480u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys,
2481 const u32 h_clock, const u32 index, u16 *pw_source)
2482{
2483 u32 qr;
2484 u16 err;
2485
2486 err = hpi_control_query(ph_subsys, h_clock, HPI_SAMPLECLOCK_SOURCE,
2487 index, 0, &qr);
2488 *pw_source = (u16)qr;
2489 return err;
2490}
2491
2492u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys,
2493 u32 h_control, u16 source)
2494{
2495 return hpi_control_param_set(ph_subsys, h_control,
2496 HPI_SAMPLECLOCK_SOURCE, source, 0);
2497}
2498
2499u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys,
2500 u32 h_control, u16 *pw_source)
2501{
2502 u16 error = 0;
2503 u32 source = 0;
2504 error = hpi_control_param1_get(ph_subsys, h_control,
2505 HPI_SAMPLECLOCK_SOURCE, &source);
2506 if (!error)
2507 if (pw_source)
2508 *pw_source = (u16)source;
2509 return error;
2510}
2511
2512u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys,
2513 const u32 h_clock, const u32 index, const u32 source,
2514 u16 *pw_source_index)
2515{
2516 u32 qr;
2517 u16 err;
2518
2519 err = hpi_control_query(ph_subsys, h_clock,
2520 HPI_SAMPLECLOCK_SOURCE_INDEX, index, source, &qr);
2521 *pw_source_index = (u16)qr;
2522 return err;
2523}
2524
2525u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys,
2526 u32 h_control, u16 source_index)
2527{
2528 return hpi_control_param_set(ph_subsys, h_control,
2529 HPI_SAMPLECLOCK_SOURCE_INDEX, source_index, 0);
2530}
2531
2532u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys,
2533 u32 h_control, u16 *pw_source_index)
2534{
2535 u16 error = 0;
2536 u32 source_index = 0;
2537 error = hpi_control_param1_get(ph_subsys, h_control,
2538 HPI_SAMPLECLOCK_SOURCE_INDEX, &source_index);
2539 if (!error)
2540 if (pw_source_index)
2541 *pw_source_index = (u16)source_index;
2542 return error;
2543}
2544
2545u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys,
2546 const u32 h_clock, const u32 index, u32 *prate)
2547{
2548 u16 err;
2549 err = hpi_control_query(ph_subsys, h_clock,
2550 HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, index, 0, prate);
2551
2552 return err;
2553}
2554
2555u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys,
2556 u32 h_control, u32 sample_rate)
2557{
2558 return hpi_control_param_set(ph_subsys, h_control,
2559 HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, sample_rate, 0);
2560}
2561
2562u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys,
2563 u32 h_control, u32 *psample_rate)
2564{
2565 u16 error = 0;
2566 u32 sample_rate = 0;
2567 error = hpi_control_param1_get(ph_subsys, h_control,
2568 HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, &sample_rate);
2569 if (!error)
2570 if (psample_rate)
2571 *psample_rate = sample_rate;
2572 return error;
2573}
2574
2575u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
2576 u32 h_control, u32 *psample_rate)
2577{
2578 u16 error = 0;
2579 u32 sample_rate = 0;
2580 error = hpi_control_param1_get(ph_subsys, h_control,
2581 HPI_SAMPLECLOCK_SAMPLERATE, &sample_rate);
2582 if (!error)
2583 if (psample_rate)
2584 *psample_rate = sample_rate;
2585 return error;
2586}
2587
2588u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys,
2589 u32 h_control, u32 enable)
2590{
2591 return hpi_control_param_set(ph_subsys, h_control,
2592 HPI_SAMPLECLOCK_AUTO, enable, 0);
2593}
2594
2595u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys,
2596 u32 h_control, u32 *penable)
2597{
2598 return hpi_control_param1_get(ph_subsys, h_control,
2599 HPI_SAMPLECLOCK_AUTO, penable);
2600}
2601
2602u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
2603 u32 h_control, u32 lock)
2604{
2605 return hpi_control_param_set(ph_subsys, h_control,
2606 HPI_SAMPLECLOCK_LOCAL_LOCK, lock, 0);
2607}
2608
2609u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
2610 u32 h_control, u32 *plock)
2611{
2612 return hpi_control_param1_get(ph_subsys, h_control,
2613 HPI_SAMPLECLOCK_LOCAL_LOCK, plock);
2614}
2615
2616u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
2617 u32 h_control, u32 index, u32 *frequency)
2618{
2619 return hpi_control_param_get(ph_subsys, h_control,
2620 HPI_TONEDETECTOR_FREQUENCY, index, 0, frequency, NULL);
2621}
2622
2623u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys,
2624 u32 h_control, u32 *state)
2625{
2626 return hpi_control_param_get(ph_subsys, h_control,
2627 HPI_TONEDETECTOR_STATE, 0, 0, (u32 *)state, NULL);
2628}
2629
2630u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
2631 u32 h_control, u32 enable)
2632{
2633 return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
2634 (u32)enable, 0);
2635}
2636
2637u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
2638 u32 h_control, u32 *enable)
2639{
2640 return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE,
2641 0, 0, (u32 *)enable, NULL);
2642}
2643
2644u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
2645 u32 h_control, u32 event_enable)
2646{
2647 return hpi_control_param_set(ph_subsys, h_control,
2648 HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0);
2649}
2650
2651u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
2652 u32 h_control, u32 *event_enable)
2653{
2654 return hpi_control_param_get(ph_subsys, h_control,
2655 HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL);
2656}
2657
2658u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
2659 u32 h_control, int threshold)
2660{
2661 return hpi_control_param_set(ph_subsys, h_control,
2662 HPI_TONEDETECTOR_THRESHOLD, (u32)threshold, 0);
2663}
2664
2665u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
2666 u32 h_control, int *threshold)
2667{
2668 return hpi_control_param_get(ph_subsys, h_control,
2669 HPI_TONEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL);
2670}
2671
2672u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
2673 u32 h_control, u32 *state)
2674{
2675 return hpi_control_param_get(ph_subsys, h_control,
2676 HPI_SILENCEDETECTOR_STATE, 0, 0, (u32 *)state, NULL);
2677}
2678
2679u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
2680 u32 h_control, u32 enable)
2681{
2682 return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
2683 (u32)enable, 0);
2684}
2685
2686u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
2687 u32 h_control, u32 *enable)
2688{
2689 return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE,
2690 0, 0, (u32 *)enable, NULL);
2691}
2692
2693u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
2694 u32 h_control, u32 event_enable)
2695{
2696 return hpi_control_param_set(ph_subsys, h_control,
2697 HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0);
2698}
2699
2700u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
2701 u32 h_control, u32 *event_enable)
2702{
2703 return hpi_control_param_get(ph_subsys, h_control,
2704 HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL);
2705}
2706
2707u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
2708 u32 h_control, u32 delay)
2709{
2710 return hpi_control_param_set(ph_subsys, h_control,
2711 HPI_SILENCEDETECTOR_DELAY, (u32)delay, 0);
2712}
2713
2714u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
2715 u32 h_control, u32 *delay)
2716{
2717 return hpi_control_param_get(ph_subsys, h_control,
2718 HPI_SILENCEDETECTOR_DELAY, 0, 0, (u32 *)delay, NULL);
2719}
2720
2721u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
2722 u32 h_control, int threshold)
2723{
2724 return hpi_control_param_set(ph_subsys, h_control,
2725 HPI_SILENCEDETECTOR_THRESHOLD, (u32)threshold, 0);
2726}
2727
2728u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
2729 u32 h_control, int *threshold)
2730{
2731 return hpi_control_param_get(ph_subsys, h_control,
2732 HPI_SILENCEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL);
2733}
2734
2735u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
2736 const u32 h_tuner, const u32 index, u16 *pw_band)
2737{
2738 u32 qr;
2739 u16 err;
2740
2741 err = hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_BAND, index, 0,
2742 &qr);
2743 *pw_band = (u16)qr;
2744 return err;
2745}
2746
2747u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2748 u16 band)
2749{
2750 return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_BAND,
2751 band, 0);
2752}
2753
2754u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2755 u16 *pw_band)
2756{
2757 u32 band = 0;
2758 u16 error = 0;
2759
2760 error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_BAND,
2761 &band);
2762 if (pw_band)
2763 *pw_band = (u16)band;
2764 return error;
2765}
2766
2767u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys,
2768 const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq)
2769{
2770 return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_FREQ, index,
2771 band, pfreq);
2772}
2773
2774u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys,
2775 u32 h_control, u32 freq_ink_hz)
2776{
2777 return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_FREQ,
2778 freq_ink_hz, 0);
2779}
2780
2781u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys,
2782 u32 h_control, u32 *pw_freq_ink_hz)
2783{
2784 return hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_FREQ,
2785 pw_freq_ink_hz);
2786}
2787
2788u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys,
2789 const u32 h_tuner, const u32 index, u16 *pw_gain)
2790{
2791 u32 qr;
2792 u16 err;
2793
2794 err = hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_BAND, index, 0,
2795 &qr);
2796 *pw_gain = (u16)qr;
2797 return err;
2798}
2799
2800u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2801 short gain)
2802{
2803 return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_GAIN,
2804 gain, 0);
2805}
2806
2807u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2808 short *pn_gain)
2809{
2810 u32 gain = 0;
2811 u16 error = 0;
2812
2813 error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_GAIN,
2814 &gain);
2815 if (pn_gain)
2816 *pn_gain = (u16)gain;
2817 return error;
2818}
2819
2820u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2821 short *pw_level)
2822{
2823 struct hpi_message hm;
2824 struct hpi_response hr;
2825 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2826 HPI_CONTROL_GET_STATE);
2827 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2828 hm.u.c.attribute = HPI_TUNER_LEVEL;
2829 hm.u.c.param1 = HPI_TUNER_LEVEL_AVERAGE;
2830 hpi_send_recv(&hm, &hr);
2831 if (pw_level)
2832 *pw_level = (short)hr.u.c.param1;
2833 return hr.error;
2834}
2835
2836u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
2837 u32 h_control, short *pw_level)
2838{
2839 struct hpi_message hm;
2840 struct hpi_response hr;
2841 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2842 HPI_CONTROL_GET_STATE);
2843 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2844 hm.u.c.attribute = HPI_TUNER_LEVEL;
2845 hm.u.c.param1 = HPI_TUNER_LEVEL_RAW;
2846 hpi_send_recv(&hm, &hr);
2847 if (pw_level)
2848 *pw_level = (short)hr.u.c.param1;
2849 return hr.error;
2850}
2851
2852u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys,
2853 const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis)
2854{
2855 return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_DEEMPHASIS,
2856 index, band, pdeemphasis);
2857}
2858
2859u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys,
2860 u32 h_control, u32 deemphasis)
2861{
2862 return hpi_control_param_set(ph_subsys, h_control,
2863 HPI_TUNER_DEEMPHASIS, deemphasis, 0);
2864}
2865
2866u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys,
2867 u32 h_control, u32 *pdeemphasis)
2868{
2869 return hpi_control_param1_get(ph_subsys, h_control,
2870 HPI_TUNER_DEEMPHASIS, pdeemphasis);
2871}
2872
2873u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys,
2874 const u32 h_tuner, u32 *pbitmap_program)
2875{
2876 return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_PROGRAM, 0, 0,
2877 pbitmap_program);
2878}
2879
2880u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2881 u32 program)
2882{
2883 return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_PROGRAM,
2884 program, 0);
2885}
2886
2887u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2888 u32 *pprogram)
2889{
2890 return hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_PROGRAM,
2891 pprogram);
2892}
2893
2894u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
2895 u32 h_control, char *psz_dsp_version, const u32 string_size)
2896{
2897 return hpi_control_get_string(ph_subsys, h_control,
2898 HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size);
2899}
2900
2901u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
2902 u32 h_control, char *psz_sdk_version, const u32 string_size)
2903{
2904 return hpi_control_get_string(ph_subsys, h_control,
2905 HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size);
2906}
2907
2908u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2909 u16 *pw_status_mask, u16 *pw_status)
2910{
2911 u32 status = 0;
2912 u16 error = 0;
2913
2914 error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_STATUS,
2915 &status);
2916 if (pw_status) {
2917 if (!error) {
2918 *pw_status_mask = (u16)(status >> 16);
2919 *pw_status = (u16)(status & 0xFFFF);
2920 } else {
2921 *pw_status_mask = 0;
2922 *pw_status = 0;
2923 }
2924 }
2925 return error;
2926}
2927
2928u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2929 u32 mode, u32 value)
2930{
2931 return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_MODE,
2932 mode, value);
2933}
2934
2935u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2936 u32 mode, u32 *pn_value)
2937{
2938 return hpi_control_param_get(ph_subsys, h_control, HPI_TUNER_MODE,
2939 mode, 0, pn_value, NULL);
2940}
2941
2942u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
2943 u32 h_control, u32 *pquality)
2944{
2945 return hpi_control_param_get(ph_subsys, h_control,
2946 HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pquality, NULL);
2947}
2948
2949u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2950 char *p_data)
2951{
2952 struct hpi_message hm;
2953 struct hpi_response hr;
2954 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
2955 HPI_CONTROL_GET_STATE);
2956 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
2957 hm.u.c.attribute = HPI_TUNER_RDS;
2958 hpi_send_recv(&hm, &hr);
2959 if (p_data) {
2960 *(u32 *)&p_data[0] = hr.u.cu.tuner.rds.data[0];
2961 *(u32 *)&p_data[4] = hr.u.cu.tuner.rds.data[1];
2962 *(u32 *)&p_data[8] = hr.u.cu.tuner.rds.bLER;
2963 }
2964 return hr.error;
2965}
2966
2967u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
2968 u32 h_control, char *psz_string, const u32 data_length)
2969{
2970 return hpi_control_get_string(ph_subsys, h_control,
2971 HPI_PAD_CHANNEL_NAME, psz_string, data_length);
2972}
2973
2974u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2975 char *psz_string, const u32 data_length)
2976{
2977 return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_ARTIST,
2978 psz_string, data_length);
2979}
2980
2981u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2982 char *psz_string, const u32 data_length)
2983{
2984 return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_TITLE,
2985 psz_string, data_length);
2986}
2987
2988u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
2989 char *psz_string, const u32 data_length)
2990{
2991 return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_COMMENT,
2992 psz_string, data_length);
2993}
2994
2995u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
2996 u32 h_control, u32 *ppTY)
2997{
2998 return hpi_control_param_get(ph_subsys, h_control,
2999 HPI_PAD_PROGRAM_TYPE, 0, 0, ppTY, NULL);
3000}
3001
3002u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3003 u32 *ppI)
3004{
3005 return hpi_control_param_get(ph_subsys, h_control, HPI_PAD_PROGRAM_ID,
3006 0, 0, ppI, NULL);
3007}
3008
3009u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
3010 const u32 h_volume, u32 *p_channels)
3011{
3012 return hpi_control_query(ph_subsys, h_volume, HPI_VOLUME_NUM_CHANNELS,
3013 0, 0, p_channels);
3014}
3015
3016u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3017 short an_log_gain[HPI_MAX_CHANNELS]
3018 )
3019{
3020 struct hpi_message hm;
3021 struct hpi_response hr;
3022 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3023 HPI_CONTROL_SET_STATE);
3024 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3025 memcpy(hm.u.c.an_log_value, an_log_gain,
3026 sizeof(short) * HPI_MAX_CHANNELS);
3027 hm.u.c.attribute = HPI_VOLUME_GAIN;
3028
3029 hpi_send_recv(&hm, &hr);
3030
3031 return hr.error;
3032}
3033
3034u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3035 short an_log_gain[HPI_MAX_CHANNELS]
3036 )
3037{
3038 struct hpi_message hm;
3039 struct hpi_response hr;
3040 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3041 HPI_CONTROL_GET_STATE);
3042 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3043 hm.u.c.attribute = HPI_VOLUME_GAIN;
3044
3045 hpi_send_recv(&hm, &hr);
3046
3047 memcpy(an_log_gain, hr.u.c.an_log_value,
3048 sizeof(short) * HPI_MAX_CHANNELS);
3049 return hr.error;
3050}
3051
3052u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3053 short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB)
3054{
3055 struct hpi_message hm;
3056 struct hpi_response hr;
3057 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3058 HPI_CONTROL_GET_STATE);
3059 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3060 hm.u.c.attribute = HPI_VOLUME_RANGE;
3061
3062 hpi_send_recv(&hm, &hr);
3063 if (hr.error) {
3064 hr.u.c.an_log_value[0] = 0;
3065 hr.u.c.an_log_value[1] = 0;
3066 hr.u.c.param1 = 0;
3067 }
3068 if (min_gain_01dB)
3069 *min_gain_01dB = hr.u.c.an_log_value[0];
3070 if (max_gain_01dB)
3071 *max_gain_01dB = hr.u.c.an_log_value[1];
3072 if (step_gain_01dB)
3073 *step_gain_01dB = (short)hr.u.c.param1;
3074 return hr.error;
3075}
3076
3077u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
3078 u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS],
3079 u32 duration_ms, u16 profile)
3080{
3081 struct hpi_message hm;
3082 struct hpi_response hr;
3083 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3084 HPI_CONTROL_SET_STATE);
3085 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3086
3087 memcpy(hm.u.c.an_log_value, an_stop_gain0_01dB,
3088 sizeof(short) * HPI_MAX_CHANNELS);
3089
3090 hm.u.c.attribute = HPI_VOLUME_AUTOFADE;
3091 hm.u.c.param1 = duration_ms;
3092 hm.u.c.param2 = profile;
3093
3094 hpi_send_recv(&hm, &hr);
3095
3096 return hr.error;
3097}
3098
3099u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3100 short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms)
3101{
3102 return hpi_volume_auto_fade_profile(ph_subsys, h_control,
3103 an_stop_gain0_01dB, duration_ms, HPI_VOLUME_AUTOFADE_LOG);
3104}
3105
3106u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3107 short an_gain0_01dB)
3108{
3109 struct hpi_message hm;
3110 struct hpi_response hr;
3111 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3112 HPI_CONTROL_SET_STATE);
3113 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3114 hm.u.c.attribute = HPI_VOX_THRESHOLD;
3115
3116 hm.u.c.an_log_value[0] = an_gain0_01dB;
3117
3118 hpi_send_recv(&hm, &hr);
3119
3120 return hr.error;
3121}
3122
3123u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
3124 short *an_gain0_01dB)
3125{
3126 struct hpi_message hm;
3127 struct hpi_response hr;
3128 hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
3129 HPI_CONTROL_GET_STATE);
3130 u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
3131 hm.u.c.attribute = HPI_VOX_THRESHOLD;
3132
3133 hpi_send_recv(&hm, &hr);
3134
3135 *an_gain0_01dB = hr.u.c.an_log_value[0];
3136
3137 return hr.error;
3138}
3139
3140static size_t strv_packet_size = MIN_STRV_PACKET_SIZE;
3141
3142static size_t entity_type_to_size[LAST_ENTITY_TYPE] = {
3143 0,
3144 sizeof(struct hpi_entity),
3145 sizeof(void *),
3146
3147 sizeof(int),
3148 sizeof(float),
3149 sizeof(double),
3150
3151 sizeof(char),
3152 sizeof(char),
3153
3154 4 * sizeof(char),
3155 16 * sizeof(char),
3156 6 * sizeof(char),
3157};
3158
3159inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
3160{
3161 return entity_ptr->header.size;
3162}
3163
3164inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
3165{
3166 return sizeof(entity_ptr->header);
3167}
3168
3169inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
3170{
3171 return hpi_entity_size(entity_ptr) -
3172 hpi_entity_header_size(entity_ptr);
3173}
3174
3175inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
3176{
3177 return hpi_entity_value_size(entity_ptr) /
3178 entity_type_to_size[entity_ptr->header.type];
3179}
3180
3181inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
3182 *entity_ptr)
3183{
3184 return (void *)(((uint8_t *) entity_ptr) +
3185 hpi_entity_size(entity_ptr));
3186}
3187
3188inline u16 hpi_entity_check_type(const enum e_entity_type t)
3189{
3190 if (t >= 0 && t < STR_TYPE_FIELD_MAX)
3191 return 0;
3192 return HPI_ERROR_ENTITY_TYPE_INVALID;
3193}
3194
3195inline u16 hpi_entity_check_role(const enum e_entity_role r)
3196{
3197 if (r >= 0 && r < STR_ROLE_FIELD_MAX)
3198 return 0;
3199 return HPI_ERROR_ENTITY_ROLE_INVALID;
3200}
3201
3202static u16 hpi_entity_get_next(struct hpi_entity *entity, int recursive_flag,
3203 void *guard_p, struct hpi_entity **next)
3204{
3205 HPI_DEBUG_ASSERT(entity != NULL);
3206 HPI_DEBUG_ASSERT(next != NULL);
3207 HPI_DEBUG_ASSERT(hpi_entity_size(entity) != 0);
3208
3209 if (guard_p <= (void *)entity) {
3210 *next = NULL;
3211 return 0;
3212 }
3213
3214 if (recursive_flag && entity->header.type == entity_type_sequence)
3215 *next = (struct hpi_entity *)entity->value;
3216 else
3217 *next = (struct hpi_entity *)hpi_entity_ptr_to_next(entity);
3218
3219 if (guard_p <= (void *)*next) {
3220 *next = NULL;
3221 return 0;
3222 }
3223
3224 HPI_DEBUG_ASSERT(guard_p >= (void *)hpi_entity_ptr_to_next(*next));
3225 return 0;
3226}
3227
3228u16 hpi_entity_find_next(struct hpi_entity *container_entity,
3229 enum e_entity_type type, enum e_entity_role role, int recursive_flag,
3230 struct hpi_entity **current_match)
3231{
3232 struct hpi_entity *tmp = NULL;
3233 void *guard_p = NULL;
3234
3235 HPI_DEBUG_ASSERT(container_entity != NULL);
3236 guard_p = hpi_entity_ptr_to_next(container_entity);
3237
3238 if (*current_match != NULL)
3239 hpi_entity_get_next(*current_match, recursive_flag, guard_p,
3240 &tmp);
3241 else
3242 hpi_entity_get_next(container_entity, 1, guard_p, &tmp);
3243
3244 while (tmp) {
3245 u16 err;
3246
3247 HPI_DEBUG_ASSERT((void *)tmp >= (void *)container_entity);
3248
3249 if ((!type || tmp->header.type == type) && (!role
3250 || tmp->header.role == role)) {
3251 *current_match = tmp;
3252 return 0;
3253 }
3254
3255 err = hpi_entity_get_next(tmp, recursive_flag, guard_p,
3256 current_match);
3257 if (err)
3258 return err;
3259
3260 tmp = *current_match;
3261 }
3262
3263 *current_match = NULL;
3264 return 0;
3265}
3266
3267void hpi_entity_free(struct hpi_entity *entity)
3268{
3269 if (entity != NULL)
3270 kfree(entity);
3271}
3272
3273static u16 hpi_entity_alloc_and_copy(struct hpi_entity *src,
3274 struct hpi_entity **dst)
3275{
3276 size_t buf_size;
3277 HPI_DEBUG_ASSERT(dst != NULL);
3278 HPI_DEBUG_ASSERT(src != NULL);
3279
3280 buf_size = hpi_entity_size(src);
3281 *dst = kmalloc(buf_size, GFP_KERNEL);
3282 if (dst == NULL)
3283 return HPI_ERROR_MEMORY_ALLOC;
3284 memcpy(*dst, src, buf_size);
3285 return 0;
3286}
3287
3288u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC,
3289 struct hpi_entity **info)
3290{
3291 struct hpi_msg_strv hm;
3292 struct hpi_res_strv *phr;
3293 u16 hpi_err;
3294 int remaining_attempts = 2;
3295 size_t resp_packet_size = 1024;
3296
3297 *info = NULL;
3298
3299 while (remaining_attempts--) {
3300 phr = kmalloc(resp_packet_size, GFP_KERNEL);
3301 HPI_DEBUG_ASSERT(phr != NULL);
3302
3303 hpi_init_message_responseV1(&hm.h, (u16)sizeof(hm), &phr->h,
3304 (u16)resp_packet_size, HPI_OBJ_CONTROL,
3305 HPI_CONTROL_GET_INFO);
3306 u32TOINDEXES(hC, &hm.h.adapter_index, &hm.h.obj_index);
3307
3308 hm.strv.header.size = sizeof(hm.strv);
3309 phr->strv.header.size = resp_packet_size - sizeof(phr->h);
3310
3311 hpi_send_recv((struct hpi_message *)&hm.h,
3312 (struct hpi_response *)&phr->h);
3313 if (phr->h.error == HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL) {
3314
3315 HPI_DEBUG_ASSERT(phr->h.specific_error >
3316 MIN_STRV_PACKET_SIZE
3317 && phr->h.specific_error < 1500);
3318 resp_packet_size = phr->h.specific_error;
3319 } else {
3320 remaining_attempts = 0;
3321 if (!phr->h.error)
3322 hpi_entity_alloc_and_copy(&phr->strv, info);
3323 }
3324
3325 hpi_err = phr->h.error;
3326 kfree(phr);
3327 }
3328
3329 return hpi_err;
3330}
3331
3332u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC,
3333 struct hpi_entity **value)
3334{
3335 struct hpi_msg_strv hm;
3336 struct hpi_res_strv *phr;
3337 u16 hpi_err;
3338 int remaining_attempts = 2;
3339
3340 *value = NULL;
3341
3342 while (remaining_attempts--) {
3343 phr = kmalloc(strv_packet_size, GFP_KERNEL);
3344 if (!phr)
3345 return HPI_ERROR_MEMORY_ALLOC;
3346
3347 hpi_init_message_responseV1(&hm.h, (u16)sizeof(hm), &phr->h,
3348 (u16)strv_packet_size, HPI_OBJ_CONTROL,
3349 HPI_CONTROL_GET_STATE);
3350 u32TOINDEXES(hC, &hm.h.adapter_index, &hm.h.obj_index);
3351
3352 hm.strv.header.size = sizeof(hm.strv);
3353 phr->strv.header.size = strv_packet_size - sizeof(phr->h);
3354
3355 hpi_send_recv((struct hpi_message *)&hm.h,
3356 (struct hpi_response *)&phr->h);
3357 if (phr->h.error == HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL) {
3358
3359 HPI_DEBUG_ASSERT(phr->h.specific_error >
3360 MIN_STRV_PACKET_SIZE
3361 && phr->h.specific_error < 1000);
3362 strv_packet_size = phr->h.specific_error;
3363 } else {
3364 remaining_attempts = 0;
3365 if (!phr->h.error)
3366 hpi_entity_alloc_and_copy(&phr->strv, value);
3367 }
3368
3369 hpi_err = phr->h.error;
3370 kfree(phr);
3371 }
3372
3373 return hpi_err;
3374}
3375
3376u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC,
3377 struct hpi_entity *value)
3378{
3379 struct hpi_msg_strv *phm;
3380 struct hpi_res_strv hr;
3381
3382 phm = kmalloc(sizeof(phm->h) + value->header.size, GFP_KERNEL);
3383 HPI_DEBUG_ASSERT(phm != NULL);
3384
3385 hpi_init_message_responseV1(&phm->h,
3386 sizeof(phm->h) + value->header.size, &hr.h, sizeof(hr),
3387 HPI_OBJ_CONTROL, HPI_CONTROL_SET_STATE);
3388 u32TOINDEXES(hC, &phm->h.adapter_index, &phm->h.obj_index);
3389 hr.strv.header.size = sizeof(hr.strv);
3390
3391 memcpy(&phm->strv, value, value->header.size);
3392 hpi_send_recv((struct hpi_message *)&phm->h,
3393 (struct hpi_response *)&hr.h);
3394
3395 return hr.h.error;
3396}
3397
3398u16 hpi_entity_alloc_and_pack(const enum e_entity_type type,
3399 const size_t item_count, const enum e_entity_role role, void *value,
3400 struct hpi_entity **entity)
3401{
3402 size_t bytes_to_copy, total_size;
3403 u16 hE = 0;
3404 *entity = NULL;
3405
3406 hE = hpi_entity_check_type(type);
3407 if (hE)
3408 return hE;
3409
3410 HPI_DEBUG_ASSERT(role > entity_role_null && type < LAST_ENTITY_ROLE);
3411
3412 bytes_to_copy = entity_type_to_size[type] * item_count;
3413 total_size = hpi_entity_header_size(*entity) + bytes_to_copy;
3414
3415 HPI_DEBUG_ASSERT(total_size >= hpi_entity_header_size(*entity)
3416 && total_size < STR_SIZE_FIELD_MAX);
3417
3418 *entity = kmalloc(total_size, GFP_KERNEL);
3419 if (*entity == NULL)
3420 return HPI_ERROR_MEMORY_ALLOC;
3421 memcpy((*entity)->value, value, bytes_to_copy);
3422 (*entity)->header.size =
3423 hpi_entity_header_size(*entity) + bytes_to_copy;
3424 (*entity)->header.type = type;
3425 (*entity)->header.role = role;
3426 return 0;
3427}
3428
3429u16 hpi_entity_copy_value_from(struct hpi_entity *entity,
3430 enum e_entity_type type, size_t item_count, void *value_dst_p)
3431{
3432 size_t bytes_to_copy;
3433
3434 if (entity->header.type != type)
3435 return HPI_ERROR_ENTITY_TYPE_MISMATCH;
3436
3437 if (hpi_entity_item_count(entity) != item_count)
3438 return HPI_ERROR_ENTITY_ITEM_COUNT;
3439
3440 bytes_to_copy = entity_type_to_size[type] * item_count;
3441 memcpy(value_dst_p, entity->value, bytes_to_copy);
3442 return 0;
3443}
3444
3445u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type,
3446 size_t *item_count, enum e_entity_role *role, void **value)
3447{
3448 u16 err = 0;
3449 HPI_DEBUG_ASSERT(entity != NULL);
3450
3451 if (type)
3452 *type = entity->header.type;
3453
3454 if (role)
3455 *role = entity->header.role;
3456
3457 if (value)
3458 *value = entity->value;
3459
3460 if (item_count != NULL) {
3461 if (entity->header.type == entity_type_sequence) {
3462 void *guard_p = hpi_entity_ptr_to_next(entity);
3463 struct hpi_entity *next = NULL;
3464 void *contents = entity->value;
3465
3466 *item_count = 0;
3467 while (contents < guard_p) {
3468 (*item_count)++;
3469 err = hpi_entity_get_next(contents, 0,
3470 guard_p, &next);
3471 if (next == NULL || err)
3472 break;
3473 contents = next;
3474 }
3475 } else {
3476 *item_count = hpi_entity_item_count(entity);
3477 }
3478 }
3479 return err;
3480}
3481
3482u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
3483 u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits)
3484{
3485 struct hpi_message hm;
3486 struct hpi_response hr;
3487 hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_OPEN);
3488 hm.adapter_index = adapter_index;
3489
3490 hpi_send_recv(&hm, &hr);
3491
3492 if (hr.error == 0) {
3493 *ph_gpio =
3494 hpi_indexes_to_handle(HPI_OBJ_GPIO, adapter_index, 0);
3495 if (pw_number_input_bits)
3496 *pw_number_input_bits = hr.u.l.number_input_bits;
3497 if (pw_number_output_bits)
3498 *pw_number_output_bits = hr.u.l.number_output_bits;
3499 } else
3500 *ph_gpio = 0;
3501 return hr.error;
3502}
3503
3504u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
3505 u16 bit_index, u16 *pw_bit_data)
3506{
3507 struct hpi_message hm;
3508 struct hpi_response hr;
3509 hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_READ_BIT);
3510 u32TOINDEX(h_gpio, &hm.adapter_index);
3511 hm.u.l.bit_index = bit_index;
3512
3513 hpi_send_recv(&hm, &hr);
3514
3515 *pw_bit_data = hr.u.l.bit_data[0];
3516 return hr.error;
3517}
3518
3519u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
3520 u16 aw_all_bit_data[4]
3521 )
3522{
3523 struct hpi_message hm;
3524 struct hpi_response hr;
3525 hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_READ_ALL);
3526 u32TOINDEX(h_gpio, &hm.adapter_index);
3527
3528 hpi_send_recv(&hm, &hr);
3529
3530 if (aw_all_bit_data) {
3531 aw_all_bit_data[0] = hr.u.l.bit_data[0];
3532 aw_all_bit_data[1] = hr.u.l.bit_data[1];
3533 aw_all_bit_data[2] = hr.u.l.bit_data[2];
3534 aw_all_bit_data[3] = hr.u.l.bit_data[3];
3535 }
3536 return hr.error;
3537}
3538
3539u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
3540 u16 bit_index, u16 bit_data)
3541{
3542 struct hpi_message hm;
3543 struct hpi_response hr;
3544 hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_WRITE_BIT);
3545 u32TOINDEX(h_gpio, &hm.adapter_index);
3546 hm.u.l.bit_index = bit_index;
3547 hm.u.l.bit_data = bit_data;
3548
3549 hpi_send_recv(&hm, &hr);
3550
3551 return hr.error;
3552}
3553
3554u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
3555 u16 aw_all_bit_data[4]
3556 )
3557{
3558 struct hpi_message hm;
3559 struct hpi_response hr;
3560 hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO,
3561 HPI_GPIO_WRITE_STATUS);
3562 u32TOINDEX(h_gpio, &hm.adapter_index);
3563
3564 hpi_send_recv(&hm, &hr);
3565
3566 if (aw_all_bit_data) {
3567 aw_all_bit_data[0] = hr.u.l.bit_data[0];
3568 aw_all_bit_data[1] = hr.u.l.bit_data[1];
3569 aw_all_bit_data[2] = hr.u.l.bit_data[2];
3570 aw_all_bit_data[3] = hr.u.l.bit_data[3];
3571 }
3572 return hr.error;
3573}
3574
3575u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys,
3576 u16 adapter_index, u32 *ph_async)
3577{
3578 struct hpi_message hm;
3579 struct hpi_response hr;
3580 hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
3581 HPI_ASYNCEVENT_OPEN);
3582 hm.adapter_index = adapter_index;
3583
3584 hpi_send_recv(&hm, &hr);
3585
3586 if (hr.error == 0)
3587
3588 *ph_async =
3589 hpi_indexes_to_handle(HPI_OBJ_ASYNCEVENT,
3590 adapter_index, 0);
3591 else
3592 *ph_async = 0;
3593 return hr.error;
3594
3595}
3596
3597u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async)
3598{
3599 struct hpi_message hm;
3600 struct hpi_response hr;
3601 hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
3602 HPI_ASYNCEVENT_OPEN);
3603 u32TOINDEX(h_async, &hm.adapter_index);
3604
3605 hpi_send_recv(&hm, &hr);
3606
3607 return hr.error;
3608}
3609
3610u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
3611 u16 maximum_events, struct hpi_async_event *p_events,
3612 u16 *pw_number_returned)
3613{
3614 return 0;
3615}
3616
3617u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys,
3618 u32 h_async, u16 *pw_count)
3619{
3620 struct hpi_message hm;
3621 struct hpi_response hr;
3622 hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
3623 HPI_ASYNCEVENT_GETCOUNT);
3624 u32TOINDEX(h_async, &hm.adapter_index);
3625
3626 hpi_send_recv(&hm, &hr);
3627
3628 if (hr.error == 0)
3629 if (pw_count)
3630 *pw_count = hr.u.as.u.count.count;
3631
3632 return hr.error;
3633}
3634
3635u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async,
3636 u16 maximum_events, struct hpi_async_event *p_events,
3637 u16 *pw_number_returned)
3638{
3639 struct hpi_message hm;
3640 struct hpi_response hr;
3641 hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
3642 HPI_ASYNCEVENT_GET);
3643 u32TOINDEX(h_async, &hm.adapter_index);
3644
3645 hpi_send_recv(&hm, &hr);
3646 if (!hr.error) {
3647 memcpy(p_events, &hr.u.as.u.event,
3648 sizeof(struct hpi_async_event));
3649 *pw_number_returned = 1;
3650 }
3651
3652 return hr.error;
3653}
3654
3655u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
3656 u32 *ph_nv_memory, u16 *pw_size_in_bytes)
3657{
3658 struct hpi_message hm;
3659 struct hpi_response hr;
3660 hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY,
3661 HPI_NVMEMORY_OPEN);
3662 hm.adapter_index = adapter_index;
3663
3664 hpi_send_recv(&hm, &hr);
3665
3666 if (hr.error == 0) {
3667 *ph_nv_memory =
3668 hpi_indexes_to_handle(HPI_OBJ_NVMEMORY, adapter_index,
3669 0);
3670 if (pw_size_in_bytes)
3671 *pw_size_in_bytes = hr.u.n.size_in_bytes;
3672 } else
3673 *ph_nv_memory = 0;
3674 return hr.error;
3675}
3676
3677u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys,
3678 u32 h_nv_memory, u16 index, u16 *pw_data)
3679{
3680 struct hpi_message hm;
3681 struct hpi_response hr;
3682 hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY,
3683 HPI_NVMEMORY_READ_BYTE);
3684 u32TOINDEX(h_nv_memory, &hm.adapter_index);
3685 hm.u.n.address = index;
3686
3687 hpi_send_recv(&hm, &hr);
3688
3689 *pw_data = hr.u.n.data;
3690 return hr.error;
3691}
3692
3693u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys,
3694 u32 h_nv_memory, u16 index, u16 data)
3695{
3696 struct hpi_message hm;
3697 struct hpi_response hr;
3698 hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY,
3699 HPI_NVMEMORY_WRITE_BYTE);
3700 u32TOINDEX(h_nv_memory, &hm.adapter_index);
3701 hm.u.n.address = index;
3702 hm.u.n.data = data;
3703
3704 hpi_send_recv(&hm, &hr);
3705
3706 return hr.error;
3707}
3708
3709u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys,
3710 u16 adapter_index, u16 profile_index, u32 *ph_profile,
3711 u16 *pw_max_profiles)
3712{
3713 struct hpi_message hm;
3714 struct hpi_response hr;
3715 hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
3716 HPI_PROFILE_OPEN_ALL);
3717 hm.adapter_index = adapter_index;
3718 hm.obj_index = profile_index;
3719 hpi_send_recv(&hm, &hr);
3720
3721 *pw_max_profiles = hr.u.p.u.o.max_profiles;
3722 if (hr.error == 0)
3723 *ph_profile =
3724 hpi_indexes_to_handle(HPI_OBJ_PROFILE, adapter_index,
3725 profile_index);
3726 else
3727 *ph_profile = 0;
3728 return hr.error;
3729}
3730
3731u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
3732 u16 bin_index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count,
3733 u32 *pmax_micro_seconds, u32 *pmin_micro_seconds)
3734{
3735 struct hpi_message hm;
3736 struct hpi_response hr;
3737 hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, HPI_PROFILE_GET);
3738 u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
3739 hm.u.p.bin_index = bin_index;
3740 hpi_send_recv(&hm, &hr);
3741 if (pw_seconds)
3742 *pw_seconds = hr.u.p.u.t.seconds;
3743 if (pmicro_seconds)
3744 *pmicro_seconds = hr.u.p.u.t.micro_seconds;
3745 if (pcall_count)
3746 *pcall_count = hr.u.p.u.t.call_count;
3747 if (pmax_micro_seconds)
3748 *pmax_micro_seconds = hr.u.p.u.t.max_micro_seconds;
3749 if (pmin_micro_seconds)
3750 *pmin_micro_seconds = hr.u.p.u.t.min_micro_seconds;
3751 return hr.error;
3752}
3753
3754u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys,
3755 u32 h_profile, u32 *putilization)
3756{
3757 struct hpi_message hm;
3758 struct hpi_response hr;
3759 hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
3760 HPI_PROFILE_GET_UTILIZATION);
3761 u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
3762 hpi_send_recv(&hm, &hr);
3763 if (hr.error) {
3764 if (putilization)
3765 *putilization = 0;
3766 } else {
3767 if (putilization)
3768 *putilization = hr.u.p.u.t.call_count;
3769 }
3770 return hr.error;
3771}
3772
3773u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
3774 u16 bin_index, char *sz_name, u16 name_length)
3775{
3776 struct hpi_message hm;
3777 struct hpi_response hr;
3778 hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
3779 HPI_PROFILE_GET_NAME);
3780 u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
3781 hm.u.p.bin_index = bin_index;
3782 hpi_send_recv(&hm, &hr);
3783 if (hr.error) {
3784 if (sz_name)
3785 strcpy(sz_name, "??");
3786 } else {
3787 if (sz_name)
3788 memcpy(sz_name, (char *)hr.u.p.u.n.sz_name,
3789 name_length);
3790 }
3791 return hr.error;
3792}
3793
3794u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile)
3795{
3796 struct hpi_message hm;
3797 struct hpi_response hr;
3798 hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
3799 HPI_PROFILE_START_ALL);
3800 u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
3801 hpi_send_recv(&hm, &hr);
3802
3803 return hr.error;
3804}
3805
3806u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile)
3807{
3808 struct hpi_message hm;
3809 struct hpi_response hr;
3810 hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
3811 HPI_PROFILE_STOP_ALL);
3812 u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
3813 hpi_send_recv(&hm, &hr);
3814
3815 return hr.error;
3816}
3817
3818u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
3819 u32 *ph_watchdog)
3820{
3821 struct hpi_message hm;
3822 struct hpi_response hr;
3823 hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG,
3824 HPI_WATCHDOG_OPEN);
3825 hm.adapter_index = adapter_index;
3826
3827 hpi_send_recv(&hm, &hr);
3828
3829 if (hr.error == 0)
3830 *ph_watchdog =
3831 hpi_indexes_to_handle(HPI_OBJ_WATCHDOG, adapter_index,
3832 0);
3833 else
3834 *ph_watchdog = 0;
3835 return hr.error;
3836}
3837
3838u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog,
3839 u32 time_millisec)
3840{
3841 struct hpi_message hm;
3842 struct hpi_response hr;
3843 hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG,
3844 HPI_WATCHDOG_SET_TIME);
3845 u32TOINDEX(h_watchdog, &hm.adapter_index);
3846 hm.u.w.time_ms = time_millisec;
3847
3848 hpi_send_recv(&hm, &hr);
3849
3850 return hr.error;
3851}
3852
3853u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog)
3854{
3855 struct hpi_message hm;
3856 struct hpi_response hr;
3857 hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG,
3858 HPI_WATCHDOG_PING);
3859 u32TOINDEX(h_watchdog, &hm.adapter_index);
3860
3861 hpi_send_recv(&hm, &hr);
3862
3863 return hr.error;
3864}
diff --git a/sound/pci/asihpi/hpimsginit.c b/sound/pci/asihpi/hpimsginit.c
new file mode 100644
index 000000000000..8e1d099ed7e4
--- /dev/null
+++ b/sound/pci/asihpi/hpimsginit.c
@@ -0,0 +1,130 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Hardware Programming Interface (HPI) Utility functions.
20
21 (C) Copyright AudioScience Inc. 2007
22*******************************************************************************/
23
24#include "hpi_internal.h"
25#include "hpimsginit.h"
26
27/* The actual message size for each object type */
28static u16 msg_size[HPI_OBJ_MAXINDEX + 1] = HPI_MESSAGE_SIZE_BY_OBJECT;
29/* The actual response size for each object type */
30static u16 res_size[HPI_OBJ_MAXINDEX + 1] = HPI_RESPONSE_SIZE_BY_OBJECT;
31/* Flag to enable alternate message type for SSX2 bypass. */
32static u16 gwSSX2_bypass;
33
34/** \internal
35 * Used by ASIO driver to disable SSX2 for a single process
36 * \param phSubSys Pointer to HPI subsystem handle.
37 * \param wBypass New bypass setting 0 = off, nonzero = on
38 * \return Previous bypass setting.
39 */
40u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass)
41{
42 u16 old_value = gwSSX2_bypass;
43
44 gwSSX2_bypass = bypass;
45
46 return old_value;
47}
48
49/** \internal
50 * initialize the HPI message structure
51 */
52static void hpi_init_message(struct hpi_message *phm, u16 object,
53 u16 function)
54{
55 memset(phm, 0, sizeof(*phm));
56 if ((object > 0) && (object <= HPI_OBJ_MAXINDEX))
57 phm->size = msg_size[object];
58 else
59 phm->size = sizeof(*phm);
60
61 if (gwSSX2_bypass)
62 phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE;
63 else
64 phm->type = HPI_TYPE_MESSAGE;
65 phm->object = object;
66 phm->function = function;
67 phm->version = 0;
68 /* Expect adapter index to be set by caller */
69}
70
71/** \internal
72 * initialize the HPI response structure
73 */
74void hpi_init_response(struct hpi_response *phr, u16 object, u16 function,
75 u16 error)
76{
77 memset(phr, 0, sizeof(*phr));
78 phr->type = HPI_TYPE_RESPONSE;
79 if ((object > 0) && (object <= HPI_OBJ_MAXINDEX))
80 phr->size = res_size[object];
81 else
82 phr->size = sizeof(*phr);
83 phr->object = object;
84 phr->function = function;
85 phr->error = error;
86 phr->specific_error = 0;
87 phr->version = 0;
88}
89
90void hpi_init_message_response(struct hpi_message *phm,
91 struct hpi_response *phr, u16 object, u16 function)
92{
93 hpi_init_message(phm, object, function);
94 /* default error return if the response is
95 not filled in by the callee */
96 hpi_init_response(phr, object, function,
97 HPI_ERROR_PROCESSING_MESSAGE);
98}
99
100static void hpi_init_messageV1(struct hpi_message_header *phm, u16 size,
101 u16 object, u16 function)
102{
103 memset(phm, 0, sizeof(*phm));
104 if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) {
105 phm->size = size;
106 phm->type = HPI_TYPE_MESSAGE;
107 phm->object = object;
108 phm->function = function;
109 phm->version = 1;
110 /* Expect adapter index to be set by caller */
111 }
112}
113
114void hpi_init_responseV1(struct hpi_response_header *phr, u16 size,
115 u16 object, u16 function)
116{
117 memset(phr, 0, sizeof(*phr));
118 phr->size = size;
119 phr->version = 1;
120 phr->type = HPI_TYPE_RESPONSE;
121 phr->error = HPI_ERROR_PROCESSING_MESSAGE;
122}
123
124void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size,
125 struct hpi_response_header *phr, u16 res_size, u16 object,
126 u16 function)
127{
128 hpi_init_messageV1(phm, msg_size, object, function);
129 hpi_init_responseV1(phr, res_size, object, function);
130}
diff --git a/sound/pci/asihpi/hpimsginit.h b/sound/pci/asihpi/hpimsginit.h
new file mode 100644
index 000000000000..864ad020c9b3
--- /dev/null
+++ b/sound/pci/asihpi/hpimsginit.h
@@ -0,0 +1,40 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Hardware Programming Interface (HPI) Utility functions
20
21 (C) Copyright AudioScience Inc. 2007
22*******************************************************************************/
23/* Initialise response headers, or msg/response pairs.
24Note that it is valid to just init a response e.g. when a lower level is preparing
25a response to a message.
26However, when sending a message, a matching response buffer always must be prepared
27*/
28
29void hpi_init_response(struct hpi_response *phr, u16 object, u16 function,
30 u16 error);
31
32void hpi_init_message_response(struct hpi_message *phm,
33 struct hpi_response *phr, u16 object, u16 function);
34
35void hpi_init_responseV1(struct hpi_response_header *phr, u16 size,
36 u16 object, u16 function);
37
38void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size,
39 struct hpi_response_header *phr, u16 res_size, u16 object,
40 u16 function);
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
new file mode 100644
index 000000000000..2ee90dc3d897
--- /dev/null
+++ b/sound/pci/asihpi/hpimsgx.c
@@ -0,0 +1,907 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Extended Message Function With Response Cacheing
20
21(C) Copyright AudioScience Inc. 2002
22*****************************************************************************/
23#define SOURCEFILE_NAME "hpimsgx.c"
24#include "hpi_internal.h"
25#include "hpimsginit.h"
26#include "hpimsgx.h"
27#include "hpidebug.h"
28
29static struct pci_device_id asihpi_pci_tbl[] = {
30#include "hpipcida.h"
31};
32
33static struct hpios_spinlock msgx_lock;
34
35static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
36
37static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
38 *pci_info)
39{
40
41 int i;
42
43 for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
44 if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
45 && asihpi_pci_tbl[i].vendor != pci_info->vendor_id)
46 continue;
47 if (asihpi_pci_tbl[i].device != PCI_ANY_ID
48 && asihpi_pci_tbl[i].device != pci_info->device_id)
49 continue;
50 if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
51 && asihpi_pci_tbl[i].subvendor !=
52 pci_info->subsys_vendor_id)
53 continue;
54 if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
55 && asihpi_pci_tbl[i].subdevice !=
56 pci_info->subsys_device_id)
57 continue;
58
59 HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i,
60 asihpi_pci_tbl[i].driver_data);
61 return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
62 }
63
64 return NULL;
65}
66
67static inline void hw_entry_point(struct hpi_message *phm,
68 struct hpi_response *phr)
69{
70
71 hpi_handler_func *ep;
72
73 if (phm->adapter_index < HPI_MAX_ADAPTERS) {
74 ep = (hpi_handler_func *) hpi_entry_points[phm->
75 adapter_index];
76 if (ep) {
77 HPI_DEBUG_MESSAGE(DEBUG, phm);
78 ep(phm, phr);
79 HPI_DEBUG_RESPONSE(phr);
80 return;
81 }
82 }
83 hpi_init_response(phr, phm->object, phm->function,
84 HPI_ERROR_PROCESSING_MESSAGE);
85}
86
87static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
88static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
89
90static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
91static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
92
93static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
94 void *h_owner);
95static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
96 void *h_owner);
97static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
98 void *h_owner);
99static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
100 void *h_owner);
101
102static void HPIMSGX__reset(u16 adapter_index);
103static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
104static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
105
106#ifndef DISABLE_PRAGMA_PACK1
107#pragma pack(push, 1)
108#endif
109
110struct hpi_subsys_response {
111 struct hpi_response_header h;
112 struct hpi_subsys_res s;
113};
114
115struct hpi_adapter_response {
116 struct hpi_response_header h;
117 struct hpi_adapter_res a;
118};
119
120struct hpi_mixer_response {
121 struct hpi_response_header h;
122 struct hpi_mixer_res m;
123};
124
125struct hpi_stream_response {
126 struct hpi_response_header h;
127 struct hpi_stream_res d;
128};
129
130struct adapter_info {
131 u16 type;
132 u16 num_instreams;
133 u16 num_outstreams;
134};
135
136struct asi_open_state {
137 int open_flag;
138 void *h_owner;
139};
140
141#ifndef DISABLE_PRAGMA_PACK1
142#pragma pack(pop)
143#endif
144
145/* Globals */
146static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
147
148static struct hpi_stream_response
149 rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
150
151static struct hpi_stream_response
152 rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
153
154static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
155
156static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS;
157
158static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
159
160/* use these to keep track of opens from user mode apps/DLLs */
161static struct asi_open_state
162 outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
163
164static struct asi_open_state
165 instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
166
167static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
168 void *h_owner)
169{
170 switch (phm->function) {
171 case HPI_SUBSYS_GET_VERSION:
172 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
173 HPI_SUBSYS_GET_VERSION, 0);
174 phr->u.s.version = HPI_VER >> 8; /* return major.minor */
175 phr->u.s.data = HPI_VER; /* return major.minor.release */
176 break;
177 case HPI_SUBSYS_OPEN:
178 /*do not propagate the message down the chain */
179 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0);
180 break;
181 case HPI_SUBSYS_CLOSE:
182 /*do not propagate the message down the chain */
183 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE,
184 0);
185 HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
186 break;
187 case HPI_SUBSYS_DRIVER_LOAD:
188 /* Initialize this module's internal state */
189 hpios_msgxlock_init(&msgx_lock);
190 memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
191 hpios_locked_mem_init();
192 /* Init subsys_findadapters response to no-adapters */
193 HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
194 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
195 HPI_SUBSYS_DRIVER_LOAD, 0);
196 /* individual HPIs dont implement driver load */
197 HPI_COMMON(phm, phr);
198 break;
199 case HPI_SUBSYS_DRIVER_UNLOAD:
200 HPI_COMMON(phm, phr);
201 HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
202 hpios_locked_mem_free_all();
203 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
204 HPI_SUBSYS_DRIVER_UNLOAD, 0);
205 return;
206
207 case HPI_SUBSYS_GET_INFO:
208 HPI_COMMON(phm, phr);
209 break;
210
211 case HPI_SUBSYS_FIND_ADAPTERS:
212 memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
213 sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
214 break;
215 case HPI_SUBSYS_GET_NUM_ADAPTERS:
216 memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
217 sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
218 phr->function = HPI_SUBSYS_GET_NUM_ADAPTERS;
219 break;
220 case HPI_SUBSYS_GET_ADAPTER:
221 {
222 int count = phm->adapter_index;
223 int index = 0;
224 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
225 HPI_SUBSYS_GET_ADAPTER, 0);
226
227 /* This is complicated by the fact that we want to
228 * "skip" 0's in the adapter list.
229 * First, make sure we are pointing to a
230 * non-zero adapter type.
231 */
232 while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
233 s.aw_adapter_list[index] == 0) {
234 index++;
235 if (index >= HPI_MAX_ADAPTERS)
236 break;
237 }
238 while (count) {
239 /* move on to the next adapter */
240 index++;
241 if (index >= HPI_MAX_ADAPTERS)
242 break;
243 while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
244 s.aw_adapter_list[index] == 0) {
245 index++;
246 if (index >= HPI_MAX_ADAPTERS)
247 break;
248 }
249 count--;
250 }
251
252 if (index < HPI_MAX_ADAPTERS) {
253 phr->u.s.adapter_index = (u16)index;
254 phr->u.s.aw_adapter_list[0] =
255 gRESP_HPI_SUBSYS_FIND_ADAPTERS.
256 s.aw_adapter_list[index];
257 } else {
258 phr->u.s.adapter_index = 0;
259 phr->u.s.aw_adapter_list[0] = 0;
260 phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
261 }
262 break;
263 }
264 case HPI_SUBSYS_CREATE_ADAPTER:
265 HPIMSGX__init(phm, phr);
266 break;
267 case HPI_SUBSYS_DELETE_ADAPTER:
268 HPIMSGX__cleanup(phm->adapter_index, h_owner);
269 {
270 struct hpi_message hm;
271 struct hpi_response hr;
272 /* call to HPI_ADAPTER_CLOSE */
273 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
274 HPI_ADAPTER_CLOSE);
275 hm.adapter_index = phm->adapter_index;
276 hw_entry_point(&hm, &hr);
277 }
278 hw_entry_point(phm, phr);
279 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
280 aw_adapter_list[phm->adapter_index]
281 = 0;
282 hpi_entry_points[phm->adapter_index] = NULL;
283 break;
284 default:
285 hw_entry_point(phm, phr);
286 break;
287 }
288}
289
290static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
291 void *h_owner)
292{
293 switch (phm->function) {
294 case HPI_ADAPTER_OPEN:
295 adapter_open(phm, phr);
296 break;
297 case HPI_ADAPTER_CLOSE:
298 adapter_close(phm, phr);
299 break;
300 default:
301 hw_entry_point(phm, phr);
302 break;
303 }
304}
305
306static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
307{
308 switch (phm->function) {
309 case HPI_MIXER_OPEN:
310 mixer_open(phm, phr);
311 break;
312 case HPI_MIXER_CLOSE:
313 mixer_close(phm, phr);
314 break;
315 default:
316 hw_entry_point(phm, phr);
317 break;
318 }
319}
320
321static void outstream_message(struct hpi_message *phm,
322 struct hpi_response *phr, void *h_owner)
323{
324 if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
325 hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
326 HPI_ERROR_INVALID_OBJ_INDEX);
327 return;
328 }
329
330 switch (phm->function) {
331 case HPI_OSTREAM_OPEN:
332 outstream_open(phm, phr, h_owner);
333 break;
334 case HPI_OSTREAM_CLOSE:
335 outstream_close(phm, phr, h_owner);
336 break;
337 default:
338 hw_entry_point(phm, phr);
339 break;
340 }
341}
342
343static void instream_message(struct hpi_message *phm,
344 struct hpi_response *phr, void *h_owner)
345{
346 if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
347 hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
348 HPI_ERROR_INVALID_OBJ_INDEX);
349 return;
350 }
351
352 switch (phm->function) {
353 case HPI_ISTREAM_OPEN:
354 instream_open(phm, phr, h_owner);
355 break;
356 case HPI_ISTREAM_CLOSE:
357 instream_close(phm, phr, h_owner);
358 break;
359 default:
360 hw_entry_point(phm, phr);
361 break;
362 }
363}
364
365/* NOTE: HPI_Message() must be defined in the driver as a wrapper for
366 * HPI_MessageEx so that functions in hpifunc.c compile.
367 */
368void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
369 void *h_owner)
370{
371 HPI_DEBUG_MESSAGE(DEBUG, phm);
372
373 if (phm->type != HPI_TYPE_MESSAGE) {
374 hpi_init_response(phr, phm->object, phm->function,
375 HPI_ERROR_INVALID_TYPE);
376 return;
377 }
378
379 if (phm->adapter_index >= HPI_MAX_ADAPTERS
380 && phm->adapter_index != HPIMSGX_ALLADAPTERS) {
381 hpi_init_response(phr, phm->object, phm->function,
382 HPI_ERROR_BAD_ADAPTER_NUMBER);
383 return;
384 }
385
386 switch (phm->object) {
387 case HPI_OBJ_SUBSYSTEM:
388 subsys_message(phm, phr, h_owner);
389 break;
390
391 case HPI_OBJ_ADAPTER:
392 adapter_message(phm, phr, h_owner);
393 break;
394
395 case HPI_OBJ_MIXER:
396 mixer_message(phm, phr);
397 break;
398
399 case HPI_OBJ_OSTREAM:
400 outstream_message(phm, phr, h_owner);
401 break;
402
403 case HPI_OBJ_ISTREAM:
404 instream_message(phm, phr, h_owner);
405 break;
406
407 default:
408 hw_entry_point(phm, phr);
409 break;
410 }
411 HPI_DEBUG_RESPONSE(phr);
412#if 1
413 if (phr->error >= HPI_ERROR_BACKEND_BASE) {
414 void *ep = NULL;
415 char *ep_name;
416
417 HPI_DEBUG_MESSAGE(ERROR, phm);
418
419 if (phm->adapter_index < HPI_MAX_ADAPTERS)
420 ep = hpi_entry_points[phm->adapter_index];
421
422 /* Don't need this? Have adapter index in debug info
423 Know at driver load time index->backend mapping */
424 if (ep == HPI_6000)
425 ep_name = "HPI_6000";
426 else if (ep == HPI_6205)
427 ep_name = "HPI_6205";
428 else
429 ep_name = "unknown";
430
431 HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name,
432 phr->error);
433
434 if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)
435 hpi_debug_data((u16 *)phm,
436 sizeof(*phm) / sizeof(u16));
437 }
438#endif
439}
440
441static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
442{
443 HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
444 memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
445 sizeof(rESP_HPI_ADAPTER_OPEN[0]));
446}
447
448static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
449{
450 HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
451 hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
452}
453
454static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
455{
456 memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
457 sizeof(rESP_HPI_MIXER_OPEN[0]));
458}
459
460static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
461{
462 hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
463}
464
465static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
466 void *h_owner)
467{
468
469 struct hpi_message hm;
470 struct hpi_response hr;
471
472 hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
473
474 hpios_msgxlock_lock(&msgx_lock);
475
476 if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
477 phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
478 else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
479 [phm->obj_index].h.error)
480 memcpy(phr,
481 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
482 obj_index],
483 sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
484 else {
485 instream_user_open[phm->adapter_index][phm->
486 obj_index].open_flag = 1;
487 hpios_msgxlock_un_lock(&msgx_lock);
488
489 /* issue a reset */
490 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
491 HPI_ISTREAM_RESET);
492 hm.adapter_index = phm->adapter_index;
493 hm.obj_index = phm->obj_index;
494 hw_entry_point(&hm, &hr);
495
496 hpios_msgxlock_lock(&msgx_lock);
497 if (hr.error) {
498 instream_user_open[phm->adapter_index][phm->
499 obj_index].open_flag = 0;
500 phr->error = hr.error;
501 } else {
502 instream_user_open[phm->adapter_index][phm->
503 obj_index].open_flag = 1;
504 instream_user_open[phm->adapter_index][phm->
505 obj_index].h_owner = h_owner;
506 memcpy(phr,
507 &rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
508 [phm->obj_index],
509 sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
510 }
511 }
512 hpios_msgxlock_un_lock(&msgx_lock);
513}
514
515static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
516 void *h_owner)
517{
518
519 struct hpi_message hm;
520 struct hpi_response hr;
521
522 hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
523
524 hpios_msgxlock_lock(&msgx_lock);
525 if (h_owner ==
526 instream_user_open[phm->adapter_index][phm->
527 obj_index].h_owner) {
528 /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
529 "instream %d owned by %p\n",
530 phm->wAdapterIndex, phm->wObjIndex, hOwner); */
531 instream_user_open[phm->adapter_index][phm->
532 obj_index].h_owner = NULL;
533 hpios_msgxlock_un_lock(&msgx_lock);
534 /* issue a reset */
535 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
536 HPI_ISTREAM_RESET);
537 hm.adapter_index = phm->adapter_index;
538 hm.obj_index = phm->obj_index;
539 hw_entry_point(&hm, &hr);
540 hpios_msgxlock_lock(&msgx_lock);
541 if (hr.error) {
542 instream_user_open[phm->adapter_index][phm->
543 obj_index].h_owner = h_owner;
544 phr->error = hr.error;
545 } else {
546 instream_user_open[phm->adapter_index][phm->
547 obj_index].open_flag = 0;
548 instream_user_open[phm->adapter_index][phm->
549 obj_index].h_owner = NULL;
550 }
551 } else {
552 HPI_DEBUG_LOG(WARNING,
553 "%p trying to close %d instream %d owned by %p\n",
554 h_owner, phm->adapter_index, phm->obj_index,
555 instream_user_open[phm->adapter_index][phm->
556 obj_index].h_owner);
557 phr->error = HPI_ERROR_OBJ_NOT_OPEN;
558 }
559 hpios_msgxlock_un_lock(&msgx_lock);
560}
561
562static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
563 void *h_owner)
564{
565
566 struct hpi_message hm;
567 struct hpi_response hr;
568
569 hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
570
571 hpios_msgxlock_lock(&msgx_lock);
572
573 if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
574 phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
575 else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
576 [phm->obj_index].h.error)
577 memcpy(phr,
578 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
579 obj_index],
580 sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
581 else {
582 outstream_user_open[phm->adapter_index][phm->
583 obj_index].open_flag = 1;
584 hpios_msgxlock_un_lock(&msgx_lock);
585
586 /* issue a reset */
587 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
588 HPI_OSTREAM_RESET);
589 hm.adapter_index = phm->adapter_index;
590 hm.obj_index = phm->obj_index;
591 hw_entry_point(&hm, &hr);
592
593 hpios_msgxlock_lock(&msgx_lock);
594 if (hr.error) {
595 outstream_user_open[phm->adapter_index][phm->
596 obj_index].open_flag = 0;
597 phr->error = hr.error;
598 } else {
599 outstream_user_open[phm->adapter_index][phm->
600 obj_index].open_flag = 1;
601 outstream_user_open[phm->adapter_index][phm->
602 obj_index].h_owner = h_owner;
603 memcpy(phr,
604 &rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
605 [phm->obj_index],
606 sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
607 }
608 }
609 hpios_msgxlock_un_lock(&msgx_lock);
610}
611
612static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
613 void *h_owner)
614{
615
616 struct hpi_message hm;
617 struct hpi_response hr;
618
619 hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
620
621 hpios_msgxlock_lock(&msgx_lock);
622
623 if (h_owner ==
624 outstream_user_open[phm->adapter_index][phm->
625 obj_index].h_owner) {
626 /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
627 "outstream %d owned by %p\n",
628 phm->wAdapterIndex, phm->wObjIndex, hOwner); */
629 outstream_user_open[phm->adapter_index][phm->
630 obj_index].h_owner = NULL;
631 hpios_msgxlock_un_lock(&msgx_lock);
632 /* issue a reset */
633 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
634 HPI_OSTREAM_RESET);
635 hm.adapter_index = phm->adapter_index;
636 hm.obj_index = phm->obj_index;
637 hw_entry_point(&hm, &hr);
638 hpios_msgxlock_lock(&msgx_lock);
639 if (hr.error) {
640 outstream_user_open[phm->adapter_index][phm->
641 obj_index].h_owner = h_owner;
642 phr->error = hr.error;
643 } else {
644 outstream_user_open[phm->adapter_index][phm->
645 obj_index].open_flag = 0;
646 outstream_user_open[phm->adapter_index][phm->
647 obj_index].h_owner = NULL;
648 }
649 } else {
650 HPI_DEBUG_LOG(WARNING,
651 "%p trying to close %d outstream %d owned by %p\n",
652 h_owner, phm->adapter_index, phm->obj_index,
653 outstream_user_open[phm->adapter_index][phm->
654 obj_index].h_owner);
655 phr->error = HPI_ERROR_OBJ_NOT_OPEN;
656 }
657 hpios_msgxlock_un_lock(&msgx_lock);
658}
659
660static u16 adapter_prepare(u16 adapter)
661{
662 struct hpi_message hm;
663 struct hpi_response hr;
664
665 /* Open the adapter and streams */
666 u16 i;
667
668 /* call to HPI_ADAPTER_OPEN */
669 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
670 HPI_ADAPTER_OPEN);
671 hm.adapter_index = adapter;
672 hw_entry_point(&hm, &hr);
673 memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
674 sizeof(rESP_HPI_ADAPTER_OPEN[0]));
675 if (hr.error)
676 return hr.error;
677
678 /* call to HPI_ADAPTER_GET_INFO */
679 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
680 HPI_ADAPTER_GET_INFO);
681 hm.adapter_index = adapter;
682 hw_entry_point(&hm, &hr);
683 if (hr.error)
684 return hr.error;
685
686 aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams;
687 aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams;
688 aDAPTER_INFO[adapter].type = hr.u.a.adapter_type;
689
690 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] =
691 hr.u.a.adapter_type;
692 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++;
693 if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS)
694 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters =
695 HPI_MAX_ADAPTERS;
696
697 /* call to HPI_OSTREAM_OPEN */
698 for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
699 hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
700 HPI_OSTREAM_OPEN);
701 hm.adapter_index = adapter;
702 hm.obj_index = i;
703 hw_entry_point(&hm, &hr);
704 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
705 sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
706 outstream_user_open[adapter][i].open_flag = 0;
707 outstream_user_open[adapter][i].h_owner = NULL;
708 }
709
710 /* call to HPI_ISTREAM_OPEN */
711 for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
712 hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
713 HPI_ISTREAM_OPEN);
714 hm.adapter_index = adapter;
715 hm.obj_index = i;
716 hw_entry_point(&hm, &hr);
717 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
718 sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
719 instream_user_open[adapter][i].open_flag = 0;
720 instream_user_open[adapter][i].h_owner = NULL;
721 }
722
723 /* call to HPI_MIXER_OPEN */
724 hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
725 hm.adapter_index = adapter;
726 hw_entry_point(&hm, &hr);
727 memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
728 sizeof(rESP_HPI_MIXER_OPEN[0]));
729
730 return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error;
731}
732
733static void HPIMSGX__reset(u16 adapter_index)
734{
735 int i;
736 u16 adapter;
737 struct hpi_response hr;
738
739 if (adapter_index == HPIMSGX_ALLADAPTERS) {
740 /* reset all responses to contain errors */
741 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
742 HPI_SUBSYS_FIND_ADAPTERS, 0);
743 memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
744 sizeof(&gRESP_HPI_SUBSYS_FIND_ADAPTERS));
745
746 for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
747
748 hpi_init_response(&hr, HPI_OBJ_ADAPTER,
749 HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
750 memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
751 sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
752
753 hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
754 HPI_ERROR_INVALID_OBJ);
755 memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
756 sizeof(rESP_HPI_MIXER_OPEN[adapter]));
757
758 for (i = 0; i < HPI_MAX_STREAMS; i++) {
759 hpi_init_response(&hr, HPI_OBJ_OSTREAM,
760 HPI_OSTREAM_OPEN,
761 HPI_ERROR_INVALID_OBJ);
762 memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
763 &hr,
764 sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
765 [i]));
766 hpi_init_response(&hr, HPI_OBJ_ISTREAM,
767 HPI_ISTREAM_OPEN,
768 HPI_ERROR_INVALID_OBJ);
769 memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
770 &hr,
771 sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
772 [i]));
773 }
774 }
775 } else if (adapter_index < HPI_MAX_ADAPTERS) {
776 rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
777 HPI_ERROR_BAD_ADAPTER;
778 rESP_HPI_MIXER_OPEN[adapter_index].h.error =
779 HPI_ERROR_INVALID_OBJ;
780 for (i = 0; i < HPI_MAX_STREAMS; i++) {
781 rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
782 HPI_ERROR_INVALID_OBJ;
783 rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
784 HPI_ERROR_INVALID_OBJ;
785 }
786 if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
787 s.aw_adapter_list[adapter_index]) {
788 gRESP_HPI_SUBSYS_FIND_ADAPTERS.
789 s.aw_adapter_list[adapter_index] = 0;
790 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--;
791 }
792 }
793}
794
795static u16 HPIMSGX__init(struct hpi_message *phm,
796 /* HPI_SUBSYS_CREATE_ADAPTER structure with */
797 /* resource list or NULL=find all */
798 struct hpi_response *phr
799 /* response from HPI_ADAPTER_GET_INFO */
800 )
801{
802 hpi_handler_func *entry_point_func;
803 struct hpi_response hr;
804
805 if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS)
806 return HPI_ERROR_BAD_ADAPTER_NUMBER;
807
808 /* Init response here so we can pass in previous adapter list */
809 hpi_init_response(&hr, phm->object, phm->function,
810 HPI_ERROR_INVALID_OBJ);
811 memcpy(hr.u.s.aw_adapter_list,
812 gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list,
813 sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list));
814
815 entry_point_func =
816 hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
817
818 if (entry_point_func) {
819 HPI_DEBUG_MESSAGE(DEBUG, phm);
820 entry_point_func(phm, &hr);
821 } else {
822 phr->error = HPI_ERROR_PROCESSING_MESSAGE;
823 return phr->error;
824 }
825 if (hr.error == 0) {
826 /* the adapter was created succesfully
827 save the mapping for future use */
828 hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
829 /* prepare adapter (pre-open streams etc.) */
830 HPI_DEBUG_LOG(DEBUG,
831 "HPI_SUBSYS_CREATE_ADAPTER successful,"
832 " preparing adapter\n");
833 adapter_prepare(hr.u.s.adapter_index);
834 }
835 memcpy(phr, &hr, hr.size);
836 return phr->error;
837}
838
839static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
840{
841 int i, adapter, adapter_limit;
842
843 if (!h_owner)
844 return;
845
846 if (adapter_index == HPIMSGX_ALLADAPTERS) {
847 adapter = 0;
848 adapter_limit = HPI_MAX_ADAPTERS;
849 } else {
850 adapter = adapter_index;
851 adapter_limit = adapter + 1;
852 }
853
854 for (; adapter < adapter_limit; adapter++) {
855 /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
856 for (i = 0; i < HPI_MAX_STREAMS; i++) {
857 if (h_owner ==
858 outstream_user_open[adapter][i].h_owner) {
859 struct hpi_message hm;
860 struct hpi_response hr;
861
862 HPI_DEBUG_LOG(DEBUG,
863 "close adapter %d ostream %d\n",
864 adapter, i);
865
866 hpi_init_message_response(&hm, &hr,
867 HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
868 hm.adapter_index = (u16)adapter;
869 hm.obj_index = (u16)i;
870 hw_entry_point(&hm, &hr);
871
872 hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
873 hw_entry_point(&hm, &hr);
874
875 hm.function = HPI_OSTREAM_GROUP_RESET;
876 hw_entry_point(&hm, &hr);
877
878 outstream_user_open[adapter][i].open_flag = 0;
879 outstream_user_open[adapter][i].h_owner =
880 NULL;
881 }
882 if (h_owner == instream_user_open[adapter][i].h_owner) {
883 struct hpi_message hm;
884 struct hpi_response hr;
885
886 HPI_DEBUG_LOG(DEBUG,
887 "close adapter %d istream %d\n",
888 adapter, i);
889
890 hpi_init_message_response(&hm, &hr,
891 HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
892 hm.adapter_index = (u16)adapter;
893 hm.obj_index = (u16)i;
894 hw_entry_point(&hm, &hr);
895
896 hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
897 hw_entry_point(&hm, &hr);
898
899 hm.function = HPI_ISTREAM_GROUP_RESET;
900 hw_entry_point(&hm, &hr);
901
902 instream_user_open[adapter][i].open_flag = 0;
903 instream_user_open[adapter][i].h_owner = NULL;
904 }
905 }
906 }
907}
diff --git a/sound/pci/asihpi/hpimsgx.h b/sound/pci/asihpi/hpimsgx.h
new file mode 100644
index 000000000000..fd49e7542a88
--- /dev/null
+++ b/sound/pci/asihpi/hpimsgx.h
@@ -0,0 +1,36 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 HPI Extended Message Handler Functions
20
21(C) Copyright AudioScience Inc. 1997-2003
22******************************************************************************/
23
24#ifndef _HPIMSGX_H_
25#define _HPIMSGX_H_
26
27#include "hpi_internal.h"
28
29#define HPIMSGX_ALLADAPTERS (0xFFFF)
30
31void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
32 void *h_owner);
33
34#define HPI_MESSAGE_LOWER_LAYER hpi_send_recv_ex
35
36#endif /* _HPIMSGX_H_ */
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
new file mode 100644
index 000000000000..7396ac54e99f
--- /dev/null
+++ b/sound/pci/asihpi/hpioctl.c
@@ -0,0 +1,484 @@
1/*******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Common Linux HPI ioctl and module probe/remove functions
20*******************************************************************************/
21#define SOURCEFILE_NAME "hpioctl.c"
22
23#include "hpi_internal.h"
24#include "hpimsginit.h"
25#include "hpidebug.h"
26#include "hpimsgx.h"
27#include "hpioctl.h"
28
29#include <linux/fs.h>
30#include <linux/slab.h>
31#include <linux/moduleparam.h>
32#include <asm/uaccess.h>
33#include <linux/stringify.h>
34
35#ifdef MODULE_FIRMWARE
36MODULE_FIRMWARE("asihpi/dsp5000.bin");
37MODULE_FIRMWARE("asihpi/dsp6200.bin");
38MODULE_FIRMWARE("asihpi/dsp6205.bin");
39MODULE_FIRMWARE("asihpi/dsp6400.bin");
40MODULE_FIRMWARE("asihpi/dsp6600.bin");
41MODULE_FIRMWARE("asihpi/dsp8700.bin");
42MODULE_FIRMWARE("asihpi/dsp8900.bin");
43#endif
44
45static int prealloc_stream_buf;
46module_param(prealloc_stream_buf, int, S_IRUGO);
47MODULE_PARM_DESC(prealloc_stream_buf,
48 "preallocate size for per-adapter stream buffer");
49
50/* Allow the debug level to be changed after module load.
51 E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel
52*/
53module_param(hpi_debug_level, int, S_IRUGO | S_IWUSR);
54MODULE_PARM_DESC(hpi_debug_level, "debug verbosity 0..5");
55
56/* List of adapters found */
57static struct hpi_adapter adapters[HPI_MAX_ADAPTERS];
58
59/* Wrapper function to HPI_Message to enable dumping of the
60 message and response types.
61*/
62static void hpi_send_recv_f(struct hpi_message *phm, struct hpi_response *phr,
63 struct file *file)
64{
65 int adapter = phm->adapter_index;
66
67 if ((adapter >= HPI_MAX_ADAPTERS || adapter < 0)
68 && (phm->object != HPI_OBJ_SUBSYSTEM))
69 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
70 else
71 hpi_send_recv_ex(phm, phr, file);
72}
73
74/* This is called from hpifunc.c functions, called by ALSA
75 * (or other kernel process) In this case there is no file descriptor
76 * available for the message cache code
77 */
78void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr)
79{
80 hpi_send_recv_f(phm, phr, HOWNER_KERNEL);
81}
82
83EXPORT_SYMBOL(hpi_send_recv);
84/* for radio-asihpi */
85
86int asihpi_hpi_release(struct file *file)
87{
88 struct hpi_message hm;
89 struct hpi_response hr;
90
91/* HPI_DEBUG_LOG(INFO,"hpi_release file %p, pid %d\n", file, current->pid); */
92 /* close the subsystem just in case the application forgot to. */
93 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
94 HPI_SUBSYS_CLOSE);
95 hpi_send_recv_ex(&hm, &hr, file);
96 return 0;
97}
98
99long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
100{
101 struct hpi_ioctl_linux __user *phpi_ioctl_data;
102 void __user *puhm;
103 void __user *puhr;
104 union hpi_message_buffer_v1 *hm;
105 union hpi_response_buffer_v1 *hr;
106 u16 res_max_size;
107 u32 uncopied_bytes;
108 struct hpi_adapter *pa = NULL;
109 int err = 0;
110
111 if (cmd != HPI_IOCTL_LINUX)
112 return -EINVAL;
113
114 hm = kmalloc(sizeof(*hm), GFP_KERNEL);
115 hr = kmalloc(sizeof(*hr), GFP_KERNEL);
116 if (!hm || !hr) {
117 err = -ENOMEM;
118 goto out;
119 }
120
121 phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
122
123 /* Read the message and response pointers from user space. */
124 get_user(puhm, &phpi_ioctl_data->phm);
125 get_user(puhr, &phpi_ioctl_data->phr);
126
127 /* Now read the message size and data from user space. */
128 get_user(hm->h.size, (u16 __user *)puhm);
129 if (hm->h.size > sizeof(*hm))
130 hm->h.size = sizeof(*hm);
131
132 /*printk(KERN_INFO "message size %d\n", hm->h.wSize); */
133
134 uncopied_bytes = copy_from_user(hm, puhm, hm->h.size);
135 if (uncopied_bytes) {
136 HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
137 err = -EFAULT;
138 goto out;
139 }
140
141 get_user(res_max_size, (u16 __user *)puhr);
142 /* printk(KERN_INFO "user response size %d\n", res_max_size); */
143 if (res_max_size < sizeof(struct hpi_response_header)) {
144 HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
145 err = -EFAULT;
146 goto out;
147 }
148
149 pa = &adapters[hm->h.adapter_index];
150 hr->h.size = 0;
151 if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
152 switch (hm->h.function) {
153 case HPI_SUBSYS_CREATE_ADAPTER:
154 case HPI_SUBSYS_DELETE_ADAPTER:
155 /* Application must not use these functions! */
156 hr->h.size = sizeof(hr->h);
157 hr->h.error = HPI_ERROR_INVALID_OPERATION;
158 hr->h.function = hm->h.function;
159 uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
160 if (uncopied_bytes)
161 err = -EFAULT;
162 else
163 err = 0;
164 goto out;
165
166 default:
167 hpi_send_recv_f(&hm->m0, &hr->r0, file);
168 }
169 } else {
170 u16 __user *ptr = NULL;
171 u32 size = 0;
172
173 /* -1=no data 0=read from user mem, 1=write to user mem */
174 int wrflag = -1;
175 u32 adapter = hm->h.adapter_index;
176
177 if ((hm->h.adapter_index > HPI_MAX_ADAPTERS) || (!pa->type)) {
178 hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
179 HPI_ADAPTER_OPEN,
180 HPI_ERROR_BAD_ADAPTER_NUMBER);
181
182 uncopied_bytes =
183 copy_to_user(puhr, hr, sizeof(hr->h));
184 if (uncopied_bytes)
185 err = -EFAULT;
186 else
187 err = 0;
188 goto out;
189 }
190
191 if (mutex_lock_interruptible(&adapters[adapter].mutex)) {
192 err = -EINTR;
193 goto out;
194 }
195
196 /* Dig out any pointers embedded in the message. */
197 switch (hm->h.function) {
198 case HPI_OSTREAM_WRITE:
199 case HPI_ISTREAM_READ:{
200 /* Yes, sparse, this is correct. */
201 ptr = (u16 __user *)hm->m0.u.d.u.data.pb_data;
202 size = hm->m0.u.d.u.data.data_size;
203
204 /* Allocate buffer according to application request.
205 ?Is it better to alloc/free for the duration
206 of the transaction?
207 */
208 if (pa->buffer_size < size) {
209 HPI_DEBUG_LOG(DEBUG,
210 "realloc adapter %d stream "
211 "buffer from %zd to %d\n",
212 hm->h.adapter_index,
213 pa->buffer_size, size);
214 if (pa->p_buffer) {
215 pa->buffer_size = 0;
216 vfree(pa->p_buffer);
217 }
218 pa->p_buffer = vmalloc(size);
219 if (pa->p_buffer)
220 pa->buffer_size = size;
221 else {
222 HPI_DEBUG_LOG(ERROR,
223 "HPI could not allocate "
224 "stream buffer size %d\n",
225 size);
226
227 mutex_unlock(&adapters
228 [adapter].mutex);
229 err = -EINVAL;
230 goto out;
231 }
232 }
233
234 hm->m0.u.d.u.data.pb_data = pa->p_buffer;
235 if (hm->h.function == HPI_ISTREAM_READ)
236 /* from card, WRITE to user mem */
237 wrflag = 1;
238 else
239 wrflag = 0;
240 break;
241 }
242
243 default:
244 size = 0;
245 break;
246 }
247
248 if (size && (wrflag == 0)) {
249 uncopied_bytes =
250 copy_from_user(pa->p_buffer, ptr, size);
251 if (uncopied_bytes)
252 HPI_DEBUG_LOG(WARNING,
253 "missed %d of %d "
254 "bytes from user\n", uncopied_bytes,
255 size);
256 }
257
258 hpi_send_recv_f(&hm->m0, &hr->r0, file);
259
260 if (size && (wrflag == 1)) {
261 uncopied_bytes =
262 copy_to_user(ptr, pa->p_buffer, size);
263 if (uncopied_bytes)
264 HPI_DEBUG_LOG(WARNING,
265 "missed %d of %d " "bytes to user\n",
266 uncopied_bytes, size);
267 }
268
269 mutex_unlock(&adapters[adapter].mutex);
270 }
271
272 /* on return response size must be set */
273 /*printk(KERN_INFO "response size %d\n", hr->h.wSize); */
274
275 if (!hr->h.size) {
276 HPI_DEBUG_LOG(ERROR, "response zero size\n");
277 err = -EFAULT;
278 goto out;
279 }
280
281 if (hr->h.size > res_max_size) {
282 HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size,
283 res_max_size);
284 /*HPI_DEBUG_MESSAGE(ERROR, hm); */
285 err = -EFAULT;
286 goto out;
287 }
288
289 uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
290 if (uncopied_bytes) {
291 HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
292 err = -EFAULT;
293 goto out;
294 }
295
296out:
297 kfree(hm);
298 kfree(hr);
299 return err;
300}
301
302int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
303 const struct pci_device_id *pci_id)
304{
305 int err, idx, nm;
306 unsigned int memlen;
307 struct hpi_message hm;
308 struct hpi_response hr;
309 struct hpi_adapter adapter;
310 struct hpi_pci pci;
311
312 memset(&adapter, 0, sizeof(adapter));
313
314 printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n",
315 pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor,
316 pci_dev->subsystem_device, pci_dev->devfn);
317
318 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
319 HPI_SUBSYS_CREATE_ADAPTER);
320 hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
321 HPI_ERROR_PROCESSING_MESSAGE);
322
323 hm.adapter_index = -1; /* an invalid index */
324
325 /* fill in HPI_PCI information from kernel provided information */
326 adapter.pci = pci_dev;
327
328 nm = HPI_MAX_ADAPTER_MEM_SPACES;
329
330 for (idx = 0; idx < nm; idx++) {
331 HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n",
332 idx, pci_dev->resource[idx].name,
333 (unsigned long long)pci_resource_start(pci_dev, idx),
334 (unsigned long long)pci_resource_end(pci_dev, idx),
335 (unsigned long long)pci_resource_flags(pci_dev, idx));
336
337 if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
338 memlen = pci_resource_len(pci_dev, idx);
339 adapter.ap_remapped_mem_base[idx] =
340 ioremap(pci_resource_start(pci_dev, idx),
341 memlen);
342 if (!adapter.ap_remapped_mem_base[idx]) {
343 HPI_DEBUG_LOG(ERROR,
344 "ioremap failed, aborting\n");
345 /* unmap previously mapped pci mem space */
346 goto err;
347 }
348 }
349
350 pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx];
351 }
352
353 /* could replace Pci with direct pointer to pci_dev for linux
354 Instead wrap accessor functions for IDs etc.
355 Would it work for windows?
356 */
357 pci.bus_number = pci_dev->bus->number;
358 pci.vendor_id = (u16)pci_dev->vendor;
359 pci.device_id = (u16)pci_dev->device;
360 pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff);
361 pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff);
362 pci.device_number = pci_dev->devfn;
363 pci.interrupt = pci_dev->irq;
364 pci.p_os_data = pci_dev;
365
366 hm.u.s.resource.bus_type = HPI_BUS_PCI;
367 hm.u.s.resource.r.pci = &pci;
368
369 /* call CreateAdapterObject on the relevant hpi module */
370 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
371 if (hr.error)
372 goto err;
373
374 if (prealloc_stream_buf) {
375 adapter.p_buffer = vmalloc(prealloc_stream_buf);
376 if (!adapter.p_buffer) {
377 HPI_DEBUG_LOG(ERROR,
378 "HPI could not allocate "
379 "kernel buffer size %d\n",
380 prealloc_stream_buf);
381 goto err;
382 }
383 }
384
385 adapter.index = hr.u.s.adapter_index;
386 adapter.type = hr.u.s.aw_adapter_list[adapter.index];
387 hm.adapter_index = adapter.index;
388
389 err = hpi_adapter_open(NULL, adapter.index);
390 if (err)
391 goto err;
392
393 adapter.snd_card_asihpi = NULL;
394 /* WARNING can't init mutex in 'adapter'
395 * and then copy it to adapters[] ?!?!
396 */
397 adapters[hr.u.s.adapter_index] = adapter;
398 mutex_init(&adapters[adapter.index].mutex);
399 pci_set_drvdata(pci_dev, &adapters[adapter.index]);
400
401 printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n",
402 adapter.type, adapter.index);
403
404 return 0;
405
406err:
407 for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
408 if (adapter.ap_remapped_mem_base[idx]) {
409 iounmap(adapter.ap_remapped_mem_base[idx]);
410 adapter.ap_remapped_mem_base[idx] = NULL;
411 }
412 }
413
414 if (adapter.p_buffer) {
415 adapter.buffer_size = 0;
416 vfree(adapter.p_buffer);
417 }
418
419 HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n");
420 return -ENODEV;
421}
422
423void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
424{
425 int idx;
426 struct hpi_message hm;
427 struct hpi_response hr;
428 struct hpi_adapter *pa;
429 pa = (struct hpi_adapter *)pci_get_drvdata(pci_dev);
430
431 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
432 HPI_SUBSYS_DELETE_ADAPTER);
433 hm.adapter_index = pa->index;
434 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
435
436 /* unmap PCI memory space, mapped during device init. */
437 for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
438 if (pa->ap_remapped_mem_base[idx]) {
439 iounmap(pa->ap_remapped_mem_base[idx]);
440 pa->ap_remapped_mem_base[idx] = NULL;
441 }
442 }
443
444 if (pa->p_buffer) {
445 pa->buffer_size = 0;
446 vfree(pa->p_buffer);
447 }
448
449 pci_set_drvdata(pci_dev, NULL);
450 /*
451 printk(KERN_INFO "PCI device (%04x:%04x,%04x:%04x,%04x),"
452 " HPI index # %d, removed.\n",
453 pci_dev->vendor, pci_dev->device,
454 pci_dev->subsystem_vendor,
455 pci_dev->subsystem_device, pci_dev->devfn,
456 pa->index);
457 */
458}
459
460void __init asihpi_init(void)
461{
462 struct hpi_message hm;
463 struct hpi_response hr;
464
465 memset(adapters, 0, sizeof(adapters));
466
467 printk(KERN_INFO "ASIHPI driver %d.%02d.%02d\n",
468 HPI_VER_MAJOR(HPI_VER), HPI_VER_MINOR(HPI_VER),
469 HPI_VER_RELEASE(HPI_VER));
470
471 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
472 HPI_SUBSYS_DRIVER_LOAD);
473 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
474}
475
476void asihpi_exit(void)
477{
478 struct hpi_message hm;
479 struct hpi_response hr;
480
481 hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
482 HPI_SUBSYS_DRIVER_UNLOAD);
483 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
484}
diff --git a/sound/pci/asihpi/hpioctl.h b/sound/pci/asihpi/hpioctl.h
new file mode 100644
index 000000000000..847f72f03fe1
--- /dev/null
+++ b/sound/pci/asihpi/hpioctl.h
@@ -0,0 +1,38 @@
1/*******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Linux HPI ioctl, and shared module init functions
20*******************************************************************************/
21
22int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
23 const struct pci_device_id *pci_id);
24void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev);
25void __init asihpi_init(void);
26void __exit asihpi_exit(void);
27
28int asihpi_hpi_release(struct file *file);
29
30long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
31
32/* This is called from hpifunc.c functions, called by ALSA
33 * (or other kernel process) In this case there is no file descriptor
34 * available for the message cache code
35 */
36void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr);
37
38#define HOWNER_KERNEL ((void *)-1)
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c
new file mode 100644
index 000000000000..de615cfdb950
--- /dev/null
+++ b/sound/pci/asihpi/hpios.c
@@ -0,0 +1,114 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19HPI Operating System function implementation for Linux
20
21(C) Copyright AudioScience Inc. 1997-2003
22******************************************************************************/
23#define SOURCEFILE_NAME "hpios.c"
24#include "hpi_internal.h"
25#include "hpidebug.h"
26#include <linux/delay.h>
27#include <linux/sched.h>
28
29void hpios_delay_micro_seconds(u32 num_micro_sec)
30{
31 if ((usecs_to_jiffies(num_micro_sec) > 1) && !in_interrupt()) {
32 /* MUST NOT SCHEDULE IN INTERRUPT CONTEXT! */
33 schedule_timeout_uninterruptible(usecs_to_jiffies
34 (num_micro_sec));
35 } else if (num_micro_sec <= 2000)
36 udelay(num_micro_sec);
37 else
38 mdelay(num_micro_sec / 1000);
39
40}
41
42void hpios_locked_mem_init(void)
43{
44}
45
46/** Allocated an area of locked memory for bus master DMA operations.
47
48On error, return -ENOMEM, and *pMemArea.size = 0
49*/
50u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size,
51 struct pci_dev *pdev)
52{
53 /*?? any benefit in using managed dmam_alloc_coherent? */
54 p_mem_area->vaddr =
55 dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle,
56 GFP_DMA32 | GFP_KERNEL);
57
58 if (p_mem_area->vaddr) {
59 HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n",
60 size, (unsigned int)p_mem_area->dma_handle,
61 p_mem_area->vaddr);
62 p_mem_area->pdev = &pdev->dev;
63 p_mem_area->size = size;
64 return 0;
65 } else {
66 HPI_DEBUG_LOG(WARNING,
67 "failed to allocate %d bytes locked memory\n", size);
68 p_mem_area->size = 0;
69 return -ENOMEM;
70 }
71}
72
73u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area)
74{
75 if (p_mem_area->size) {
76 dma_free_coherent(p_mem_area->pdev, p_mem_area->size,
77 p_mem_area->vaddr, p_mem_area->dma_handle);
78 HPI_DEBUG_LOG(DEBUG, "freed %lu bytes, dma 0x%x vma %p\n",
79 (unsigned long)p_mem_area->size,
80 (unsigned int)p_mem_area->dma_handle,
81 p_mem_area->vaddr);
82 p_mem_area->size = 0;
83 return 0;
84 } else {
85 return 1;
86 }
87}
88
89void hpios_locked_mem_free_all(void)
90{
91}
92
93void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx,
94 unsigned int length)
95{
96 HPI_DEBUG_LOG(DEBUG, "mapping %d %s %08llx-%08llx %04llx len 0x%x\n",
97 idx, pci_dev->resource[idx].name,
98 (unsigned long long)pci_resource_start(pci_dev, idx),
99 (unsigned long long)pci_resource_end(pci_dev, idx),
100 (unsigned long long)pci_resource_flags(pci_dev, idx), length);
101
102 if (!(pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM)) {
103 HPI_DEBUG_LOG(ERROR, "not an io memory resource\n");
104 return NULL;
105 }
106
107 if (length > pci_resource_len(pci_dev, idx)) {
108 HPI_DEBUG_LOG(ERROR, "resource too small for requested %d \n",
109 length);
110 return NULL;
111 }
112
113 return ioremap(pci_resource_start(pci_dev, idx), length);
114}
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h
new file mode 100644
index 000000000000..a62c3f1e5f09
--- /dev/null
+++ b/sound/pci/asihpi/hpios.h
@@ -0,0 +1,178 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19HPI Operating System Specific macros for Linux Kernel driver
20
21(C) Copyright AudioScience Inc. 1997-2003
22******************************************************************************/
23#ifndef _HPIOS_H_
24#define _HPIOS_H_
25
26#undef HPI_OS_LINUX_KERNEL
27#define HPI_OS_LINUX_KERNEL
28
29#define HPI_OS_DEFINED
30#define HPI_KERNEL_MODE
31
32#define HPI_REASSIGN_DUPLICATE_ADAPTER_IDX
33
34#include <linux/io.h>
35#include <asm/system.h>
36#include <linux/ioctl.h>
37#include <linux/kernel.h>
38#include <linux/string.h>
39#include <linux/device.h>
40#include <linux/firmware.h>
41#include <linux/interrupt.h>
42#include <linux/pci.h>
43
44#define HPI_NO_OS_FILE_OPS
45
46#ifdef CONFIG_64BIT
47#define HPI64BIT
48#endif
49
50/** Details of a memory area allocated with pci_alloc_consistent
51Need all info for parameters to pci_free_consistent
52*/
53struct consistent_dma_area {
54 struct device *pdev;
55 /* looks like dma-mapping dma_devres ?! */
56 size_t size;
57 void *vaddr;
58 dma_addr_t dma_handle;
59};
60
61static inline u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area
62 *locked_mem_handle, u32 *p_physical_addr)
63{
64 *p_physical_addr = locked_mem_handle->dma_handle;
65 return 0;
66}
67
68static inline u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area
69 *locked_mem_handle, void **pp_virtual_addr)
70{
71 *pp_virtual_addr = locked_mem_handle->vaddr;
72 return 0;
73}
74
75static inline u16 hpios_locked_mem_valid(struct consistent_dma_area
76 *locked_mem_handle)
77{
78 return locked_mem_handle->size != 0;
79}
80
81struct hpi_ioctl_linux {
82 void __user *phm;
83 void __user *phr;
84};
85
86/* Conflict?: H is already used by a number of drivers hid, bluetooth hci,
87 and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is ununsed command
88*/
89#define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux)
90
91#define HPI_DEBUG_FLAG_ERROR KERN_ERR
92#define HPI_DEBUG_FLAG_WARNING KERN_WARNING
93#define HPI_DEBUG_FLAG_NOTICE KERN_NOTICE
94#define HPI_DEBUG_FLAG_INFO KERN_INFO
95#define HPI_DEBUG_FLAG_DEBUG KERN_DEBUG
96#define HPI_DEBUG_FLAG_VERBOSE KERN_DEBUG /* kernel has no verbose */
97
98#include <linux/spinlock.h>
99
100#define HPI_LOCKING
101
102struct hpios_spinlock {
103 spinlock_t lock; /* SEE hpios_spinlock */
104 int lock_context;
105};
106
107/* The reason for all this evilness is that ALSA calls some of a drivers
108 * operators in atomic context, and some not. But all our functions channel
109 * through the HPI_Message conduit, so we can't handle the different context
110 * per function
111 */
112#define IN_LOCK_BH 1
113#define IN_LOCK_IRQ 0
114static inline void cond_lock(struct hpios_spinlock *l)
115{
116 if (irqs_disabled()) {
117 /* NO bh or isr can execute on this processor,
118 so ordinary lock will do
119 */
120 spin_lock(&((l)->lock));
121 l->lock_context = IN_LOCK_IRQ;
122 } else {
123 spin_lock_bh(&((l)->lock));
124 l->lock_context = IN_LOCK_BH;
125 }
126}
127
128static inline void cond_unlock(struct hpios_spinlock *l)
129{
130 if (l->lock_context == IN_LOCK_BH)
131 spin_unlock_bh(&((l)->lock));
132 else
133 spin_unlock(&((l)->lock));
134}
135
136#define hpios_msgxlock_init(obj) spin_lock_init(&(obj)->lock)
137#define hpios_msgxlock_lock(obj) cond_lock(obj)
138#define hpios_msgxlock_un_lock(obj) cond_unlock(obj)
139
140#define hpios_dsplock_init(obj) spin_lock_init(&(obj)->dsp_lock.lock)
141#define hpios_dsplock_lock(obj) cond_lock(&(obj)->dsp_lock)
142#define hpios_dsplock_unlock(obj) cond_unlock(&(obj)->dsp_lock)
143
144#ifdef CONFIG_SND_DEBUG
145#define HPI_DEBUG
146#endif
147
148#define HPI_ALIST_LOCKING
149#define hpios_alistlock_init(obj) spin_lock_init(&((obj)->list_lock.lock))
150#define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
151#define hpios_alistlock_un_lock(obj) spin_unlock(&((obj)->list_lock.lock))
152
153struct hpi_adapter {
154 /* mutex prevents contention for one card
155 between multiple user programs (via ioctl) */
156 struct mutex mutex;
157 u16 index;
158 u16 type;
159
160 /* ALSA card structure */
161 void *snd_card_asihpi;
162
163 char *p_buffer;
164 size_t buffer_size;
165 struct pci_dev *pci;
166 void __iomem *ap_remapped_mem_base[HPI_MAX_ADAPTER_MEM_SPACES];
167};
168
169static inline void hpios_unmap_io(void __iomem *addr,
170 unsigned long size)
171{
172 iounmap(addr);
173}
174
175void __iomem *hpios_map_io(struct pci_dev *pci_dev, int idx,
176 unsigned int length);
177
178#endif
diff --git a/sound/pci/asihpi/hpipcida.h b/sound/pci/asihpi/hpipcida.h
new file mode 100644
index 000000000000..bb30868ce1a3
--- /dev/null
+++ b/sound/pci/asihpi/hpipcida.h
@@ -0,0 +1,37 @@
1/******************************************************************************
2
3 AudioScience HPI driver
4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation;
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Array initializer for PCI card IDs
20
21(C) Copyright AudioScience Inc. 1998-2003
22*******************************************************************************/
23
24/*NOTE: when adding new lines to this header file
25 they MUST be grouped by HPI entry point.
26*/
27
28{
29HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
30 HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
31 (kernel_ulong_t) HPI_6205}
32, {
33HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
34 HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
35 (kernel_ulong_t) HPI_6000}
36, {
370}