aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 12:41:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 12:41:44 -0400
commit7f06a8b26aba1dc03b42272dc0089a800372c575 (patch)
tree7c67198f83d069eb13fd417e022d111b7e4c82a1 /sound/pci
parentc3ad33c9bcb6616999953af76f16318120fe3691 (diff)
parentd71f4cece4bd97d05592836202fc04ff2e7817e3 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (250 commits) ALSA: hda: Storage class should be before const qualifier ASoC: tpa6130a2: Remove CPVSS and HPVdd supplies ASoC: tpa6130a2: Define output pins with SND_SOC_DAPM_OUTPUT ASoC: sdp4430 - add sdp4430 pcm ops to DAI. ASoC: TWL6040: Enable earphone path in codec ASoC: SDP4430: Add support for Earphone speaker ASoC: SDP4430: Add sdp4430 machine driver ASoC: tlv320dac33: Avoid powering off while in BIAS_OFF ASoC: tlv320dac33: Use dev_dbg in dac33_hard_power function ALSA: sound/pci/asihpi: Use kzalloc ALSA: hdmi - dont fail on extra nodes ALSA: intelhdmi - add id for the CougarPoint chipset ALSA: intelhdmi - user friendly codec name ALSA: intelhdmi - add dependency on SND_DYNAMIC_MINORS ALSA: asihpi: incorrect range check ALSA: asihpi: testing the wrong variable ALSA: es1688: add pedantic range checks ARM: McBSP: Add support for omap4 in McBSP driver ARM: McBSP: Fix request for irq in OMAP4 OMAP: McBSP: Add 32-bit mode support ...
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/Kconfig32
-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.c1840
-rw-r--r--sound/pci/asihpi/hpi6000.h70
-rw-r--r--sound/pci/asihpi/hpi6205.c2331
-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
-rw-r--r--sound/pci/cs4281.c40
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c19
-rw-r--r--sound/pci/emu10k1/emuproc.c51
-rw-r--r--sound/pci/es1968.c129
-rw-r--r--sound/pci/hda/Kconfig1
-rw-r--r--sound/pci/hda/hda_codec.c76
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/hda_intel.c109
-rw-r--r--sound/pci/hda/patch_analog.c21
-rw-r--r--sound/pci/hda/patch_conexant.c157
-rw-r--r--sound/pci/hda/patch_hdmi.c10
-rw-r--r--sound/pci/hda/patch_intelhdmi.c21
-rw-r--r--sound/pci/hda/patch_realtek.c238
-rw-r--r--sound/pci/ice1712/aureon.c89
-rw-r--r--sound/pci/maestro3.c139
-rw-r--r--sound/pci/mixart/mixart.c79
42 files changed, 19305 insertions, 314 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1298c68d6bf..e7a8cd058ef 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
@@ -501,6 +513,16 @@ config SND_ES1968
501 To compile this driver as a module, choose M here: the module 513 To compile this driver as a module, choose M here: the module
502 will be called snd-es1968. 514 will be called snd-es1968.
503 515
516config SND_ES1968_INPUT
517 bool "Enable input device for es1968 volume buttons"
518 depends on SND_ES1968
519 depends on INPUT=y || INPUT=SND_ES1968
520 help
521 If you say Y here, you will get an input device which reports
522 keypresses for the volume buttons connected to the es1968 chip.
523 If you say N the buttons will directly control the master volume.
524 It is recommended to say Y.
525
504config SND_FM801 526config SND_FM801
505 tristate "ForteMedia FM801" 527 tristate "ForteMedia FM801"
506 select SND_OPL3_LIB 528 select SND_OPL3_LIB
@@ -655,6 +677,16 @@ config SND_MAESTRO3
655 To compile this driver as a module, choose M here: the module 677 To compile this driver as a module, choose M here: the module
656 will be called snd-maestro3. 678 will be called snd-maestro3.
657 679
680config SND_MAESTRO3_INPUT
681 bool "Enable input device for maestro3 volume buttons"
682 depends on SND_MAESTRO3
683 depends on INPUT=y || INPUT=SND_MAESTRO3
684 help
685 If you say Y here, you will get an input device which reports
686 keypresses for the volume buttons connected to the maestro3 chip.
687 If you say N the buttons will directly control the master volume.
688 It is recommended to say Y.
689
658config SND_MIXART 690config SND_MIXART
659 tristate "Digigram miXart" 691 tristate "Digigram miXart"
660 select SND_HWDEP 692 select SND_HWDEP
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index ecfc609d2b9..9cf4348ec13 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 00000000000..391830a4556
--- /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 00000000000..f74c7372b3d
--- /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 00000000000..99400de6c07
--- /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 00000000000..839ecb2e4b6
--- /dev/null
+++ b/sound/pci/asihpi/hpi6000.c
@@ -0,0 +1,1840 @@
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 = kzalloc(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 /* create the adapter object based on the resource information */
459 /*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */
460 ao.pci = *phm->u.s.resource.r.pci;
461
462 error = create_adapter_obj(&ao, &os_error_code);
463 if (!error)
464 error = hpi_add_adapter(&ao);
465 if (error) {
466 phr->u.s.data = os_error_code;
467 kfree(ao.priv);
468 phr->error = error;
469 return;
470 }
471 /* need to update paParentAdapter */
472 pao = hpi_find_adapter(ao.index);
473 if (!pao) {
474 /* We just added this adapter, why can't we find it!? */
475 HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
476 phr->error = 950;
477 return;
478 }
479
480 for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
481 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
482 phw->ado[dsp_index].pa_parent_adapter = pao;
483 }
484
485 phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
486 phr->u.s.adapter_index = ao.index;
487 phr->u.s.num_adapters++;
488 phr->error = 0;
489}
490
491static void subsys_delete_adapter(struct hpi_message *phm,
492 struct hpi_response *phr)
493{
494 struct hpi_adapter_obj *pao = NULL;
495 struct hpi_hw_obj *phw;
496
497 pao = hpi_find_adapter(phm->adapter_index);
498 if (!pao)
499 return;
500
501 phw = (struct hpi_hw_obj *)pao->priv;
502
503 if (pao->has_control_cache)
504 hpi_free_control_cache(phw->p_cache);
505
506 hpi_delete_adapter(pao);
507 kfree(phw);
508
509 phr->error = 0;
510}
511
512/* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */
513static short create_adapter_obj(struct hpi_adapter_obj *pao,
514 u32 *pos_error_code)
515{
516 short boot_error = 0;
517 u32 dsp_index = 0;
518 u32 control_cache_size = 0;
519 u32 control_cache_count = 0;
520 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
521
522 /* init error reporting */
523 pao->dsp_crashed = 0;
524
525 /* The PCI2040 has the following address map */
526 /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
527 /* BAR1 - 32K = HPI registers on DSP */
528 phw->dw2040_HPICSR = pao->pci.ap_mem_base[0];
529 phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1];
530 HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR,
531 phw->dw2040_HPIDSP);
532
533 /* set addresses for the possible DSP HPI interfaces */
534 for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
535 phw->ado[dsp_index].prHPI_control =
536 phw->dw2040_HPIDSP + (CONTROL +
537 DSP_SPACING * dsp_index);
538
539 phw->ado[dsp_index].prHPI_address =
540 phw->dw2040_HPIDSP + (ADDRESS +
541 DSP_SPACING * dsp_index);
542 phw->ado[dsp_index].prHPI_data =
543 phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index);
544
545 phw->ado[dsp_index].prHPI_data_auto_inc =
546 phw->dw2040_HPIDSP + (DATA_AUTOINC +
547 DSP_SPACING * dsp_index);
548
549 HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n",
550 phw->ado[dsp_index].prHPI_control,
551 phw->ado[dsp_index].prHPI_address,
552 phw->ado[dsp_index].prHPI_data,
553 phw->ado[dsp_index].prHPI_data_auto_inc);
554
555 phw->ado[dsp_index].pa_parent_adapter = pao;
556 }
557
558 phw->pCI2040HPI_error_count = 0;
559 pao->has_control_cache = 0;
560
561 /* Set the default number of DSPs on this card */
562 /* This is (conditionally) adjusted after bootloading */
563 /* of the first DSP in the bootload section. */
564 phw->num_dsp = 1;
565
566 boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code);
567 if (boot_error)
568 return boot_error;
569
570 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
571
572 phw->message_buffer_address_on_dsp = 0L;
573 phw->response_buffer_address_on_dsp = 0L;
574
575 /* get info about the adapter by asking the adapter */
576 /* send a HPI_ADAPTER_GET_INFO message */
577 {
578 struct hpi_message hM;
579 struct hpi_response hR0; /* response from DSP 0 */
580 struct hpi_response hR1; /* response from DSP 1 */
581 u16 error = 0;
582
583 HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
584 memset(&hM, 0, sizeof(hM));
585 hM.type = HPI_TYPE_MESSAGE;
586 hM.size = sizeof(struct hpi_message);
587 hM.object = HPI_OBJ_ADAPTER;
588 hM.function = HPI_ADAPTER_GET_INFO;
589 hM.adapter_index = 0;
590 memset(&hR0, 0, sizeof(hR0));
591 memset(&hR1, 0, sizeof(hR1));
592 hR0.size = sizeof(hR0);
593 hR1.size = sizeof(hR1);
594
595 error = hpi6000_message_response_sequence(pao, 0, &hM, &hR0);
596 if (hR0.error) {
597 HPI_DEBUG_LOG(DEBUG, "message error %d\n", hR0.error);
598 return hR0.error;
599 }
600 if (phw->num_dsp == 2) {
601 error = hpi6000_message_response_sequence(pao, 1, &hM,
602 &hR1);
603 if (error)
604 return error;
605 }
606 pao->adapter_type = hR0.u.a.adapter_type;
607 pao->index = hR0.u.a.adapter_index;
608 }
609
610 memset(&phw->control_cache[0], 0,
611 sizeof(struct hpi_control_cache_single) *
612 HPI_NMIXER_CONTROLS);
613 /* Read the control cache length to figure out if it is turned on */
614 control_cache_size =
615 hpi_read_word(&phw->ado[0],
616 HPI_HIF_ADDR(control_cache_size_in_bytes));
617 if (control_cache_size) {
618 control_cache_count =
619 hpi_read_word(&phw->ado[0],
620 HPI_HIF_ADDR(control_cache_count));
621 pao->has_control_cache = 1;
622
623 phw->p_cache =
624 hpi_alloc_control_cache(control_cache_count,
625 control_cache_size, (struct hpi_control_cache_info *)
626 &phw->control_cache[0]
627 );
628 } else
629 pao->has_control_cache = 0;
630
631 HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n",
632 pao->adapter_type, pao->index);
633 pao->open = 0; /* upon creation the adapter is closed */
634 return 0;
635}
636
637/************************************************************************/
638/* ADAPTER */
639
640static void adapter_get_asserts(struct hpi_adapter_obj *pao,
641 struct hpi_message *phm, struct hpi_response *phr)
642{
643#ifndef HIDE_PCI_ASSERTS
644 /* if we have PCI2040 asserts then collect them */
645 if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
646 phr->u.a.serial_number =
647 gw_pci_read_asserts * 100 + gw_pci_write_asserts;
648 phr->u.a.adapter_index = 1; /* assert count */
649 phr->u.a.adapter_type = -1; /* "dsp index" */
650 strcpy(phr->u.a.sz_adapter_assert, "PCI2040 error");
651 gw_pci_read_asserts = 0;
652 gw_pci_write_asserts = 0;
653 phr->error = 0;
654 } else
655#endif
656 hw_message(pao, phm, phr); /*get DSP asserts */
657
658 return;
659}
660
661/************************************************************************/
662/* LOW-LEVEL */
663
664static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
665 u32 *pos_error_code)
666{
667 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
668 short error;
669 u32 timeout;
670 u32 read = 0;
671 u32 i = 0;
672 u32 data = 0;
673 u32 j = 0;
674 u32 test_addr = 0x80000000;
675 u32 test_data = 0x00000001;
676 u32 dw2040_reset = 0;
677 u32 dsp_index = 0;
678 u32 endian = 0;
679 u32 adapter_info = 0;
680 u32 delay = 0;
681
682 struct dsp_code dsp_code;
683 u16 boot_load_family = 0;
684
685 /* NOTE don't use wAdapterType in this routine. It is not setup yet */
686
687 switch (pao->pci.subsys_device_id) {
688 case 0x5100:
689 case 0x5110: /* ASI5100 revB or higher with C6711D */
690 case 0x6100:
691 case 0x6200:
692 boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
693 break;
694 case 0x8800:
695 boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x8800);
696 break;
697 default:
698 return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
699 }
700
701 /* reset all DSPs, indicate two DSPs are present
702 * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode
703 */
704 endian = 0;
705 dw2040_reset = 0x0003000F;
706 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
707
708 /* read back register to make sure PCI2040 chip is functioning
709 * note that bits 4..15 are read-only and so should always return zero,
710 * even though we wrote 1 to them
711 */
712 for (i = 0; i < 1000; i++)
713 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
714 if (delay != dw2040_reset) {
715 HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
716 delay);
717 return HPI6000_ERROR_INIT_PCI2040;
718 }
719
720 /* Indicate that DSP#0,1 is a C6X */
721 iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH);
722 /* set Bit30 and 29 - which will prevent Target aborts from being
723 * issued upon HPI or GP error
724 */
725 iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET);
726
727 /* isolate DSP HAD8 line from PCI2040 so that
728 * Little endian can be set by pullup
729 */
730 dw2040_reset = dw2040_reset & (~(endian << 3));
731 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
732
733 phw->ado[0].c_dsp_rev = 'B'; /* revB */
734 phw->ado[1].c_dsp_rev = 'B'; /* revB */
735
736 /*Take both DSPs out of reset, setting HAD8 to the correct Endian */
737 dw2040_reset = dw2040_reset & (~0x00000001); /* start DSP 0 */
738 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
739 dw2040_reset = dw2040_reset & (~0x00000002); /* start DSP 1 */
740 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
741
742 /* set HAD8 back to PCI2040, now that DSP set to little endian mode */
743 dw2040_reset = dw2040_reset & (~0x00000008);
744 iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
745 /*delay to allow DSP to get going */
746 for (i = 0; i < 100; i++)
747 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
748
749 /* loop through all DSPs, downloading DSP code */
750 for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
751 struct dsp_obj *pdo = &phw->ado[dsp_index];
752
753 /* configure DSP so that we download code into the SRAM */
754 /* set control reg for little endian, HWOB=1 */
755 iowrite32(0x00010001, pdo->prHPI_control);
756
757 /* test access to the HPI address register (HPIA) */
758 test_data = 0x00000001;
759 for (j = 0; j < 32; j++) {
760 iowrite32(test_data, pdo->prHPI_address);
761 data = ioread32(pdo->prHPI_address);
762 if (data != test_data) {
763 HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n",
764 test_data, data, dsp_index);
765 return HPI6000_ERROR_INIT_DSPHPI;
766 }
767 test_data = test_data << 1;
768 }
769
770/* if C6713 the setup PLL to generate 225MHz from 25MHz.
771* Since the PLLDIV1 read is sometimes wrong, even on a C6713,
772* we're going to do this unconditionally
773*/
774/* PLLDIV1 should have a value of 8000 after reset */
775/*
776 if (HpiReadWord(pdo,0x01B7C118) == 0x8000)
777*/
778 {
779 /* C6713 datasheet says we cannot program PLL from HPI,
780 * and indeed if we try to set the PLL multiply from the
781 * HPI, the PLL does not seem to lock,
782 * so we enable the PLL and use the default of x 7
783 */
784 /* bypass PLL */
785 hpi_write_word(pdo, 0x01B7C100, 0x0000);
786 for (i = 0; i < 100; i++)
787 delay = ioread32(phw->dw2040_HPICSR +
788 HPI_RESET);
789
790 /* ** use default of PLL x7 ** */
791 /* EMIF = 225/3=75MHz */
792 hpi_write_word(pdo, 0x01B7C120, 0x8002);
793 /* peri = 225/2 */
794 hpi_write_word(pdo, 0x01B7C11C, 0x8001);
795 /* cpu = 225/1 */
796 hpi_write_word(pdo, 0x01B7C118, 0x8000);
797 /* ~200us delay */
798 for (i = 0; i < 2000; i++)
799 delay = ioread32(phw->dw2040_HPICSR +
800 HPI_RESET);
801 /* PLL not bypassed */
802 hpi_write_word(pdo, 0x01B7C100, 0x0001);
803 /* ~200us delay */
804 for (i = 0; i < 2000; i++)
805 delay = ioread32(phw->dw2040_HPICSR +
806 HPI_RESET);
807 }
808
809 /* test r/w to internal DSP memory
810 * C6711 has L2 cache mapped to 0x0 when reset
811 *
812 * revB - because of bug 3.0.1 last HPI read
813 * (before HPI address issued) must be non-autoinc
814 */
815 /* test each bit in the 32bit word */
816 for (i = 0; i < 100; i++) {
817 test_addr = 0x00000000;
818 test_data = 0x00000001;
819 for (j = 0; j < 32; j++) {
820 hpi_write_word(pdo, test_addr + i, test_data);
821 data = hpi_read_word(pdo, test_addr + i);
822 if (data != test_data) {
823 HPI_DEBUG_LOG(ERROR,
824 "DSP mem %x %x %x %x\n",
825 test_addr + i, test_data,
826 data, dsp_index);
827
828 return HPI6000_ERROR_INIT_DSPINTMEM;
829 }
830 test_data = test_data << 1;
831 }
832 }
833
834 /* memory map of ASI6200
835 00000000-0000FFFF 16Kx32 internal program
836 01800000-019FFFFF Internal peripheral
837 80000000-807FFFFF CE0 2Mx32 SDRAM running @ 100MHz
838 90000000-9000FFFF CE1 Async peripherals:
839
840 EMIF config
841 ------------
842 Global EMIF control
843 0 -
844 1 -
845 2 -
846 3 CLK2EN = 1 CLKOUT2 enabled
847 4 CLK1EN = 0 CLKOUT1 disabled
848 5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT
849 6 -
850 7 NOHOLD = 1 external HOLD disabled
851 8 HOLDA = 0 HOLDA output is low
852 9 HOLD = 0 HOLD input is low
853 10 ARDY = 1 ARDY input is high
854 11 BUSREQ = 0 BUSREQ output is low
855 12,13 Reserved = 1
856 */
857 hpi_write_word(pdo, 0x01800000, 0x34A8);
858
859 /* EMIF CE0 setup - 2Mx32 Sync DRAM
860 31..28 Wr setup
861 27..22 Wr strobe
862 21..20 Wr hold
863 19..16 Rd setup
864 15..14 -
865 13..8 Rd strobe
866 7..4 MTYPE 0011 Sync DRAM 32bits
867 3 Wr hold MSB
868 2..0 Rd hold
869 */
870 hpi_write_word(pdo, 0x01800008, 0x00000030);
871
872 /* EMIF SDRAM Extension
873 31-21 0
874 20 WR2RD = 0
875 19-18 WR2DEAC = 1
876 17 WR2WR = 0
877 16-15 R2WDQM = 2
878 14-12 RD2WR = 4
879 11-10 RD2DEAC = 1
880 9 RD2RD = 1
881 8-7 THZP = 10b
882 6-5 TWR = 2-1 = 01b (tWR = 10ns)
883 4 TRRD = 0b = 2 ECLK (tRRD = 14ns)
884 3-1 TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK)
885 1 CAS latency = 3 ECLK
886 (for Micron 2M32-7 operating at 100Mhz)
887 */
888
889 /* need to use this else DSP code crashes */
890 hpi_write_word(pdo, 0x01800020, 0x001BDF29);
891
892 /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
893 31 - -
894 30 SDBSZ 1 4 bank
895 29..28 SDRSZ 00 11 row address pins
896 27..26 SDCSZ 01 8 column address pins
897 25 RFEN 1 refersh enabled
898 24 INIT 1 init SDRAM
899 23..20 TRCD 0001
900 19..16 TRP 0001
901 15..12 TRC 0110
902 11..0 - -
903 */
904 /* need to use this else DSP code crashes */
905 hpi_write_word(pdo, 0x01800018, 0x47117000);
906
907 /* EMIF SDRAM Refresh Timing */
908 hpi_write_word(pdo, 0x0180001C, 0x00000410);
909
910 /*MIF CE1 setup - Async peripherals
911 @100MHz bus speed, each cycle is 10ns,
912 31..28 Wr setup = 1
913 27..22 Wr strobe = 3 30ns
914 21..20 Wr hold = 1
915 19..16 Rd setup =1
916 15..14 Ta = 2
917 13..8 Rd strobe = 3 30ns
918 7..4 MTYPE 0010 Async 32bits
919 3 Wr hold MSB =0
920 2..0 Rd hold = 1
921 */
922 {
923 u32 cE1 =
924 (1L << 28) | (3L << 22) | (1L << 20) | (1L <<
925 16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L;
926 hpi_write_word(pdo, 0x01800004, cE1);
927 }
928
929 /* delay a little to allow SDRAM and DSP to "get going" */
930
931 for (i = 0; i < 1000; i++)
932 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
933
934 /* test access to SDRAM */
935 {
936 test_addr = 0x80000000;
937 test_data = 0x00000001;
938 /* test each bit in the 32bit word */
939 for (j = 0; j < 32; j++) {
940 hpi_write_word(pdo, test_addr, test_data);
941 data = hpi_read_word(pdo, test_addr);
942 if (data != test_data) {
943 HPI_DEBUG_LOG(ERROR,
944 "DSP dram %x %x %x %x\n",
945 test_addr, test_data, data,
946 dsp_index);
947
948 return HPI6000_ERROR_INIT_SDRAM1;
949 }
950 test_data = test_data << 1;
951 }
952 /* test every Nth address in the DRAM */
953#define DRAM_SIZE_WORDS 0x200000 /*2_mx32 */
954#define DRAM_INC 1024
955 test_addr = 0x80000000;
956 test_data = 0x0;
957 for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
958 hpi_write_word(pdo, test_addr + i, test_data);
959 test_data++;
960 }
961 test_addr = 0x80000000;
962 test_data = 0x0;
963 for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
964 data = hpi_read_word(pdo, test_addr + i);
965 if (data != test_data) {
966 HPI_DEBUG_LOG(ERROR,
967 "DSP dram %x %x %x %x\n",
968 test_addr + i, test_data,
969 data, dsp_index);
970 return HPI6000_ERROR_INIT_SDRAM2;
971 }
972 test_data++;
973 }
974
975 }
976
977 /* write the DSP code down into the DSPs memory */
978 /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */
979 dsp_code.ps_dev = pao->pci.p_os_data;
980
981 error = hpi_dsp_code_open(boot_load_family, &dsp_code,
982 pos_error_code);
983
984 if (error)
985 return error;
986
987 while (1) {
988 u32 length;
989 u32 address;
990 u32 type;
991 u32 *pcode;
992
993 error = hpi_dsp_code_read_word(&dsp_code, &length);
994 if (error)
995 break;
996 if (length == 0xFFFFFFFF)
997 break; /* end of code */
998
999 error = hpi_dsp_code_read_word(&dsp_code, &address);
1000 if (error)
1001 break;
1002 error = hpi_dsp_code_read_word(&dsp_code, &type);
1003 if (error)
1004 break;
1005 error = hpi_dsp_code_read_block(length, &dsp_code,
1006 &pcode);
1007 if (error)
1008 break;
1009 error = hpi6000_dsp_block_write32(pao, (u16)dsp_index,
1010 address, pcode, length);
1011 if (error)
1012 break;
1013 }
1014
1015 if (error) {
1016 hpi_dsp_code_close(&dsp_code);
1017 return error;
1018 }
1019 /* verify that code was written correctly */
1020 /* this time through, assume no errors in DSP code file/array */
1021 hpi_dsp_code_rewind(&dsp_code);
1022 while (1) {
1023 u32 length;
1024 u32 address;
1025 u32 type;
1026 u32 *pcode;
1027
1028 hpi_dsp_code_read_word(&dsp_code, &length);
1029 if (length == 0xFFFFFFFF)
1030 break; /* end of code */
1031
1032 hpi_dsp_code_read_word(&dsp_code, &address);
1033 hpi_dsp_code_read_word(&dsp_code, &type);
1034 hpi_dsp_code_read_block(length, &dsp_code, &pcode);
1035
1036 for (i = 0; i < length; i++) {
1037 data = hpi_read_word(pdo, address);
1038 if (data != *pcode) {
1039 error = HPI6000_ERROR_INIT_VERIFY;
1040 HPI_DEBUG_LOG(ERROR,
1041 "DSP verify %x %x %x %x\n",
1042 address, *pcode, data,
1043 dsp_index);
1044 break;
1045 }
1046 pcode++;
1047 address += 4;
1048 }
1049 if (error)
1050 break;
1051 }
1052 hpi_dsp_code_close(&dsp_code);
1053 if (error)
1054 return error;
1055
1056 /* zero out the hostmailbox */
1057 {
1058 u32 address = HPI_HIF_ADDR(host_cmd);
1059 for (i = 0; i < 4; i++) {
1060 hpi_write_word(pdo, address, 0);
1061 address += 4;
1062 }
1063 }
1064 /* write the DSP number into the hostmailbox */
1065 /* structure before starting the DSP */
1066 hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index);
1067
1068 /* write the DSP adapter Info into the */
1069 /* hostmailbox before starting the DSP */
1070 if (dsp_index > 0)
1071 hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info),
1072 adapter_info);
1073
1074 /* step 3. Start code by sending interrupt */
1075 iowrite32(0x00030003, pdo->prHPI_control);
1076 for (i = 0; i < 10000; i++)
1077 delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
1078
1079 /* wait for a non-zero value in hostcmd -
1080 * indicating initialization is complete
1081 *
1082 * Init could take a while if DSP checks SDRAM memory
1083 * Was 200000. Increased to 2000000 for ASI8801 so we
1084 * don't get 938 errors.
1085 */
1086 timeout = 2000000;
1087 while (timeout) {
1088 do {
1089 read = hpi_read_word(pdo,
1090 HPI_HIF_ADDR(host_cmd));
1091 } while (--timeout
1092 && hpi6000_check_PCI2040_error_flag(pao,
1093 H6READ));
1094
1095 if (read)
1096 break;
1097 /* The following is a workaround for bug #94:
1098 * Bluescreen on install and subsequent boots on a
1099 * DELL PowerEdge 600SC PC with 1.8GHz P4 and
1100 * ServerWorks chipset. Without this delay the system
1101 * locks up with a bluescreen (NOT GPF or pagefault).
1102 */
1103 else
1104 hpios_delay_micro_seconds(1000);
1105 }
1106 if (timeout == 0)
1107 return HPI6000_ERROR_INIT_NOACK;
1108
1109 /* read the DSP adapter Info from the */
1110 /* hostmailbox structure after starting the DSP */
1111 if (dsp_index == 0) {
1112 /*u32 dwTestData=0; */
1113 u32 mask = 0;
1114
1115 adapter_info =
1116 hpi_read_word(pdo,
1117 HPI_HIF_ADDR(adapter_info));
1118 if (HPI_ADAPTER_FAMILY_ASI
1119 (HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER
1120 (adapter_info)) ==
1121 HPI_ADAPTER_FAMILY_ASI(0x6200))
1122 /* all 6200 cards have this many DSPs */
1123 phw->num_dsp = 2;
1124
1125 /* test that the PLD is programmed */
1126 /* and we can read/write 24bits */
1127#define PLD_BASE_ADDRESS 0x90000000L /*for ASI6100/6200/8800 */
1128
1129 switch (boot_load_family) {
1130 case HPI_ADAPTER_FAMILY_ASI(0x6200):
1131 /* ASI6100/6200 has 24bit path to FPGA */
1132 mask = 0xFFFFFF00L;
1133 /* ASI5100 uses AX6 code, */
1134 /* but has no PLD r/w register to test */
1135 if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
1136 subsys_device_id) ==
1137 HPI_ADAPTER_FAMILY_ASI(0x5100))
1138 mask = 0x00000000L;
1139 break;
1140 case HPI_ADAPTER_FAMILY_ASI(0x8800):
1141 /* ASI8800 has 16bit path to FPGA */
1142 mask = 0xFFFF0000L;
1143 break;
1144 }
1145 test_data = 0xAAAAAA00L & mask;
1146 /* write to 24 bit Debug register (D31-D8) */
1147 hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1148 read = hpi_read_word(pdo,
1149 PLD_BASE_ADDRESS + 4L) & mask;
1150 if (read != test_data) {
1151 HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1152 read);
1153 return HPI6000_ERROR_INIT_PLDTEST1;
1154 }
1155 test_data = 0x55555500L & mask;
1156 hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
1157 read = hpi_read_word(pdo,
1158 PLD_BASE_ADDRESS + 4L) & mask;
1159 if (read != test_data) {
1160 HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
1161 read);
1162 return HPI6000_ERROR_INIT_PLDTEST2;
1163 }
1164 }
1165 } /* for numDSP */
1166 return 0;
1167}
1168
1169#define PCI_TIMEOUT 100
1170
1171static int hpi_set_address(struct dsp_obj *pdo, u32 address)
1172{
1173 u32 timeout = PCI_TIMEOUT;
1174
1175 do {
1176 iowrite32(address, pdo->prHPI_address);
1177 } while (hpi6000_check_PCI2040_error_flag(pdo->pa_parent_adapter,
1178 H6WRITE)
1179 && --timeout);
1180
1181 if (timeout)
1182 return 0;
1183
1184 return 1;
1185}
1186
1187/* write one word to the HPI port */
1188static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data)
1189{
1190 if (hpi_set_address(pdo, address))
1191 return;
1192 iowrite32(data, pdo->prHPI_data);
1193}
1194
1195/* read one word from the HPI port */
1196static u32 hpi_read_word(struct dsp_obj *pdo, u32 address)
1197{
1198 u32 data = 0;
1199
1200 if (hpi_set_address(pdo, address))
1201 return 0; /*? no way to return error */
1202
1203 /* take care of errata in revB DSP (2.0.1) */
1204 data = ioread32(pdo->prHPI_data);
1205 return data;
1206}
1207
1208/* write a block of 32bit words to the DSP HPI port using auto-inc mode */
1209static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1210 u32 length)
1211{
1212 u16 length16 = length - 1;
1213
1214 if (length == 0)
1215 return;
1216
1217 if (hpi_set_address(pdo, address))
1218 return;
1219
1220 iowrite32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1221
1222 /* take care of errata in revB DSP (2.0.1) */
1223 /* must end with non auto-inc */
1224 iowrite32(*(pdata + length - 1), pdo->prHPI_data);
1225}
1226
1227/** read a block of 32bit words from the DSP HPI port using auto-inc mode
1228 */
1229static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
1230 u32 length)
1231{
1232 u16 length16 = length - 1;
1233
1234 if (length == 0)
1235 return;
1236
1237 if (hpi_set_address(pdo, address))
1238 return;
1239
1240 ioread32_rep(pdo->prHPI_data_auto_inc, pdata, length16);
1241
1242 /* take care of errata in revB DSP (2.0.1) */
1243 /* must end with non auto-inc */
1244 *(pdata + length - 1) = ioread32(pdo->prHPI_data);
1245}
1246
1247static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
1248 u16 dsp_index, u32 hpi_address, u32 *source, u32 count)
1249{
1250 struct dsp_obj *pdo =
1251 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1252 u32 time_out = PCI_TIMEOUT;
1253 int c6711_burst_size = 128;
1254 u32 local_hpi_address = hpi_address;
1255 int local_count = count;
1256 int xfer_size;
1257 u32 *pdata = source;
1258
1259 while (local_count) {
1260 if (local_count > c6711_burst_size)
1261 xfer_size = c6711_burst_size;
1262 else
1263 xfer_size = local_count;
1264
1265 time_out = PCI_TIMEOUT;
1266 do {
1267 hpi_write_block(pdo, local_hpi_address, pdata,
1268 xfer_size);
1269 } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1270 && --time_out);
1271
1272 if (!time_out)
1273 break;
1274 pdata += xfer_size;
1275 local_hpi_address += sizeof(u32) * xfer_size;
1276 local_count -= xfer_size;
1277 }
1278
1279 if (time_out)
1280 return 0;
1281 else
1282 return 1;
1283}
1284
1285static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
1286 u16 dsp_index, u32 hpi_address, u32 *dest, u32 count)
1287{
1288 struct dsp_obj *pdo =
1289 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1290 u32 time_out = PCI_TIMEOUT;
1291 int c6711_burst_size = 16;
1292 u32 local_hpi_address = hpi_address;
1293 int local_count = count;
1294 int xfer_size;
1295 u32 *pdata = dest;
1296 u32 loop_count = 0;
1297
1298 while (local_count) {
1299 if (local_count > c6711_burst_size)
1300 xfer_size = c6711_burst_size;
1301 else
1302 xfer_size = local_count;
1303
1304 time_out = PCI_TIMEOUT;
1305 do {
1306 hpi_read_block(pdo, local_hpi_address, pdata,
1307 xfer_size);
1308 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1309 && --time_out);
1310 if (!time_out)
1311 break;
1312
1313 pdata += xfer_size;
1314 local_hpi_address += sizeof(u32) * xfer_size;
1315 local_count -= xfer_size;
1316 loop_count++;
1317 }
1318
1319 if (time_out)
1320 return 0;
1321 else
1322 return 1;
1323}
1324
1325static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
1326 u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr)
1327{
1328 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
1329 struct dsp_obj *pdo = &phw->ado[dsp_index];
1330 u32 timeout;
1331 u16 ack;
1332 u32 address;
1333 u32 length;
1334 u32 *p_data;
1335 u16 error = 0;
1336
1337 /* does the DSP we are referencing exist? */
1338 if (dsp_index >= phw->num_dsp)
1339 return HPI6000_ERROR_MSG_INVALID_DSP_INDEX;
1340
1341 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1342 if (ack & HPI_HIF_ERROR_MASK) {
1343 pao->dsp_crashed++;
1344 return HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT;
1345 }
1346 pao->dsp_crashed = 0;
1347
1348 /* send the message */
1349
1350 /* get the address and size */
1351 if (phw->message_buffer_address_on_dsp == 0) {
1352 timeout = TIMEOUT;
1353 do {
1354 address =
1355 hpi_read_word(pdo,
1356 HPI_HIF_ADDR(message_buffer_address));
1357 phw->message_buffer_address_on_dsp = address;
1358 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1359 && --timeout);
1360 if (!timeout)
1361 return HPI6000_ERROR_MSG_GET_ADR;
1362 } else
1363 address = phw->message_buffer_address_on_dsp;
1364
1365 /* dwLength = sizeof(struct hpi_message); */
1366 length = phm->size;
1367
1368 /* send it */
1369 p_data = (u32 *)phm;
1370 if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
1371 (u16)length / 4))
1372 return HPI6000_ERROR_MSG_RESP_BLOCKWRITE32;
1373
1374 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_GET_RESP))
1375 return HPI6000_ERROR_MSG_RESP_GETRESPCMD;
1376 hpi6000_send_dsp_interrupt(pdo);
1377
1378 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_RESP);
1379 if (ack & HPI_HIF_ERROR_MASK)
1380 return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
1381
1382 /* get the address and size */
1383 if (phw->response_buffer_address_on_dsp == 0) {
1384 timeout = TIMEOUT;
1385 do {
1386 address =
1387 hpi_read_word(pdo,
1388 HPI_HIF_ADDR(response_buffer_address));
1389 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1390 && --timeout);
1391 phw->response_buffer_address_on_dsp = address;
1392
1393 if (!timeout)
1394 return HPI6000_ERROR_RESP_GET_ADR;
1395 } else
1396 address = phw->response_buffer_address_on_dsp;
1397
1398 /* read the length of the response back from the DSP */
1399 timeout = TIMEOUT;
1400 do {
1401 length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1402 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1403 if (!timeout)
1404 length = sizeof(struct hpi_response);
1405
1406 /* get it */
1407 p_data = (u32 *)phr;
1408 if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
1409 (u16)length / 4))
1410 return HPI6000_ERROR_MSG_RESP_BLOCKREAD32;
1411
1412 /* set i/f back to idle */
1413 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1414 return HPI6000_ERROR_MSG_RESP_IDLECMD;
1415 hpi6000_send_dsp_interrupt(pdo);
1416
1417 error = hpi_validate_response(phm, phr);
1418 return error;
1419}
1420
1421/* have to set up the below defines to match stuff in the MAP file */
1422
1423#define MSG_ADDRESS (HPI_HIF_BASE+0x18)
1424#define MSG_LENGTH 11
1425#define RESP_ADDRESS (HPI_HIF_BASE+0x44)
1426#define RESP_LENGTH 16
1427#define QUEUE_START (HPI_HIF_BASE+0x88)
1428#define QUEUE_SIZE 0x8000
1429
1430static short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords)
1431{
1432/*#define CHECKING // comment this line in to enable checking */
1433#ifdef CHECKING
1434 if (address < (u32)MSG_ADDRESS)
1435 return 0;
1436 if (address > (u32)(QUEUE_START + QUEUE_SIZE))
1437 return 0;
1438 if ((address + (length_in_dwords << 2)) >
1439 (u32)(QUEUE_START + QUEUE_SIZE))
1440 return 0;
1441#else
1442 (void)address;
1443 (void)length_in_dwords;
1444 return 1;
1445#endif
1446}
1447
1448static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1449 struct hpi_message *phm, struct hpi_response *phr)
1450{
1451 struct dsp_obj *pdo =
1452 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1453 u32 data_sent = 0;
1454 u16 ack;
1455 u32 length, address;
1456 u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1457 u16 time_out = 8;
1458
1459 (void)phr;
1460
1461 /* round dwDataSize down to nearest 4 bytes */
1462 while ((data_sent < (phm->u.d.u.data.data_size & ~3L))
1463 && --time_out) {
1464 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1465 if (ack & HPI_HIF_ERROR_MASK)
1466 return HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT;
1467
1468 if (hpi6000_send_host_command(pao, dsp_index,
1469 HPI_HIF_SEND_DATA))
1470 return HPI6000_ERROR_SEND_DATA_CMD;
1471
1472 hpi6000_send_dsp_interrupt(pdo);
1473
1474 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_SEND_DATA);
1475
1476 if (ack & HPI_HIF_ERROR_MASK)
1477 return HPI6000_ERROR_SEND_DATA_ACK;
1478
1479 do {
1480 /* get the address and size */
1481 address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1482 /* DSP returns number of DWORDS */
1483 length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1484 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1485
1486 if (!hpi6000_send_data_check_adr(address, length))
1487 return HPI6000_ERROR_SEND_DATA_ADR;
1488
1489 /* send the data. break data into 512 DWORD blocks (2K bytes)
1490 * and send using block write. 2Kbytes is the max as this is the
1491 * memory window given to the HPI data register by the PCI2040
1492 */
1493
1494 {
1495 u32 len = length;
1496 u32 blk_len = 512;
1497 while (len) {
1498 if (len < blk_len)
1499 blk_len = len;
1500 if (hpi6000_dsp_block_write32(pao, dsp_index,
1501 address, p_data, blk_len))
1502 return HPI6000_ERROR_SEND_DATA_WRITE;
1503 address += blk_len * 4;
1504 p_data += blk_len;
1505 len -= blk_len;
1506 }
1507 }
1508
1509 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1510 return HPI6000_ERROR_SEND_DATA_IDLECMD;
1511
1512 hpi6000_send_dsp_interrupt(pdo);
1513
1514 data_sent += length * 4;
1515 }
1516 if (!time_out)
1517 return HPI6000_ERROR_SEND_DATA_TIMEOUT;
1518 return 0;
1519}
1520
1521static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
1522 struct hpi_message *phm, struct hpi_response *phr)
1523{
1524 struct dsp_obj *pdo =
1525 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1526 u32 data_got = 0;
1527 u16 ack;
1528 u32 length, address;
1529 u32 *p_data = (u32 *)phm->u.d.u.data.pb_data;
1530
1531 (void)phr; /* this parameter not used! */
1532
1533 /* round dwDataSize down to nearest 4 bytes */
1534 while (data_got < (phm->u.d.u.data.data_size & ~3L)) {
1535 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
1536 if (ack & HPI_HIF_ERROR_MASK)
1537 return HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT;
1538
1539 if (hpi6000_send_host_command(pao, dsp_index,
1540 HPI_HIF_GET_DATA))
1541 return HPI6000_ERROR_GET_DATA_CMD;
1542 hpi6000_send_dsp_interrupt(pdo);
1543
1544 ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_DATA);
1545
1546 if (ack & HPI_HIF_ERROR_MASK)
1547 return HPI6000_ERROR_GET_DATA_ACK;
1548
1549 /* get the address and size */
1550 do {
1551 address = hpi_read_word(pdo, HPI_HIF_ADDR(address));
1552 length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
1553 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ));
1554
1555 /* read the data */
1556 {
1557 u32 len = length;
1558 u32 blk_len = 512;
1559 while (len) {
1560 if (len < blk_len)
1561 blk_len = len;
1562 if (hpi6000_dsp_block_read32(pao, dsp_index,
1563 address, p_data, blk_len))
1564 return HPI6000_ERROR_GET_DATA_READ;
1565 address += blk_len * 4;
1566 p_data += blk_len;
1567 len -= blk_len;
1568 }
1569 }
1570
1571 if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE))
1572 return HPI6000_ERROR_GET_DATA_IDLECMD;
1573 hpi6000_send_dsp_interrupt(pdo);
1574
1575 data_got += length * 4;
1576 }
1577 return 0;
1578}
1579
1580static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo)
1581{
1582 iowrite32(0x00030003, pdo->prHPI_control); /* DSPINT */
1583}
1584
1585static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
1586 u16 dsp_index, u32 host_cmd)
1587{
1588 struct dsp_obj *pdo =
1589 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1590 u32 timeout = TIMEOUT;
1591
1592 /* set command */
1593 do {
1594 hpi_write_word(pdo, HPI_HIF_ADDR(host_cmd), host_cmd);
1595 /* flush the FIFO */
1596 hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1597 } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) && --timeout);
1598
1599 /* reset the interrupt bit */
1600 iowrite32(0x00040004, pdo->prHPI_control);
1601
1602 if (timeout)
1603 return 0;
1604 else
1605 return 1;
1606}
1607
1608/* if the PCI2040 has recorded an HPI timeout, reset the error and return 1 */
1609static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
1610 u16 read_or_write)
1611{
1612 u32 hPI_error;
1613
1614 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
1615
1616 /* read the error bits from the PCI2040 */
1617 hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1618 if (hPI_error) {
1619 /* reset the error flag */
1620 iowrite32(0L, phw->dw2040_HPICSR + HPI_ERROR_REPORT);
1621 phw->pCI2040HPI_error_count++;
1622 if (read_or_write == 1)
1623 gw_pci_read_asserts++; /************* inc global */
1624 else
1625 gw_pci_write_asserts++;
1626 return 1;
1627 } else
1628 return 0;
1629}
1630
1631static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
1632 u32 ack_value)
1633{
1634 struct dsp_obj *pdo =
1635 &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
1636 u32 ack = 0L;
1637 u32 timeout;
1638 u32 hPIC = 0L;
1639
1640 /* wait for host interrupt to signal ack is ready */
1641 timeout = TIMEOUT;
1642 while (--timeout) {
1643 hPIC = ioread32(pdo->prHPI_control);
1644 if (hPIC & 0x04) /* 0x04 = HINT from DSP */
1645 break;
1646 }
1647 if (timeout == 0)
1648 return HPI_HIF_ERROR_MASK;
1649
1650 /* wait for dwAckValue */
1651 timeout = TIMEOUT;
1652 while (--timeout) {
1653 /* read the ack mailbox */
1654 ack = hpi_read_word(pdo, HPI_HIF_ADDR(dsp_ack));
1655 if (ack == ack_value)
1656 break;
1657 if ((ack & HPI_HIF_ERROR_MASK)
1658 && !hpi6000_check_PCI2040_error_flag(pao, H6READ))
1659 break;
1660 /*for (i=0;i<1000;i++) */
1661 /* dwPause=i+1; */
1662 }
1663 if (ack & HPI_HIF_ERROR_MASK)
1664 /* indicates bad read from DSP -
1665 typically 0xffffff is read for some reason */
1666 ack = HPI_HIF_ERROR_MASK;
1667
1668 if (timeout == 0)
1669 ack = HPI_HIF_ERROR_MASK;
1670 return (short)ack;
1671}
1672
1673static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
1674 struct hpi_message *phm)
1675{
1676 const u16 dsp_index = 0;
1677 struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
1678 struct dsp_obj *pdo = &phw->ado[dsp_index];
1679 u32 timeout;
1680 u32 cache_dirty_flag;
1681 u16 err;
1682
1683 hpios_dsplock_lock(pao);
1684
1685 timeout = TIMEOUT;
1686 do {
1687 cache_dirty_flag =
1688 hpi_read_word((struct dsp_obj *)pdo,
1689 HPI_HIF_ADDR(control_cache_is_dirty));
1690 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
1691 if (!timeout) {
1692 err = HPI6000_ERROR_CONTROL_CACHE_PARAMS;
1693 goto unlock;
1694 }
1695
1696 if (cache_dirty_flag) {
1697 /* read the cached controls */
1698 u32 address;
1699 u32 length;
1700
1701 timeout = TIMEOUT;
1702 if (pdo->control_cache_address_on_dsp == 0) {
1703 do {
1704 address =
1705 hpi_read_word((struct dsp_obj *)pdo,
1706 HPI_HIF_ADDR(control_cache_address));
1707
1708 length = hpi_read_word((struct dsp_obj *)pdo,
1709 HPI_HIF_ADDR
1710 (control_cache_size_in_bytes));
1711 } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)
1712 && --timeout);
1713 if (!timeout) {
1714 err = HPI6000_ERROR_CONTROL_CACHE_ADDRLEN;
1715 goto unlock;
1716 }
1717 pdo->control_cache_address_on_dsp = address;
1718 pdo->control_cache_length_on_dsp = length;
1719 } else {
1720 address = pdo->control_cache_address_on_dsp;
1721 length = pdo->control_cache_length_on_dsp;
1722 }
1723
1724 if (hpi6000_dsp_block_read32(pao, dsp_index, address,
1725 (u32 *)&phw->control_cache[0],
1726 length / sizeof(u32))) {
1727 err = HPI6000_ERROR_CONTROL_CACHE_READ;
1728 goto unlock;
1729 }
1730 do {
1731 hpi_write_word((struct dsp_obj *)pdo,
1732 HPI_HIF_ADDR(control_cache_is_dirty), 0);
1733 /* flush the FIFO */
1734 hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd));
1735 } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE)
1736 && --timeout);
1737 if (!timeout) {
1738 err = HPI6000_ERROR_CONTROL_CACHE_FLUSH;
1739 goto unlock;
1740 }
1741
1742 }
1743 err = 0;
1744
1745unlock:
1746 hpios_dsplock_unlock(pao);
1747 return err;
1748}
1749
1750/** Get dsp index for multi DSP adapters only */
1751static u16 get_dsp_index(struct hpi_adapter_obj *pao, struct hpi_message *phm)
1752{
1753 u16 ret = 0;
1754 switch (phm->object) {
1755 case HPI_OBJ_ISTREAM:
1756 if (phm->obj_index < 2)
1757 ret = 1;
1758 break;
1759 case HPI_OBJ_PROFILE:
1760 ret = phm->obj_index;
1761 break;
1762 default:
1763 break;
1764 }
1765 return ret;
1766}
1767
1768/** Complete transaction with DSP
1769
1770Send message, get response, send or get stream data if any.
1771*/
1772static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
1773 struct hpi_response *phr)
1774{
1775 u16 error = 0;
1776 u16 dsp_index = 0;
1777 u16 num_dsp = ((struct hpi_hw_obj *)pao->priv)->num_dsp;
1778 hpios_dsplock_lock(pao);
1779
1780 if (num_dsp < 2)
1781 dsp_index = 0;
1782 else {
1783 dsp_index = get_dsp_index(pao, phm);
1784
1785 /* is this checked on the DSP anyway? */
1786 if ((phm->function == HPI_ISTREAM_GROUP_ADD)
1787 || (phm->function == HPI_OSTREAM_GROUP_ADD)) {
1788 struct hpi_message hm;
1789 u16 add_index;
1790 hm.obj_index = phm->u.d.u.stream.stream_index;
1791 hm.object = phm->u.d.u.stream.object_type;
1792 add_index = get_dsp_index(pao, &hm);
1793 if (add_index != dsp_index) {
1794 phr->error = HPI_ERROR_NO_INTERDSP_GROUPS;
1795 return;
1796 }
1797 }
1798 }
1799 error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
1800
1801 /* maybe an error response */
1802 if (error) {
1803 /* something failed in the HPI/DSP interface */
1804 phr->error = error;
1805 /* just the header of the response is valid */
1806 phr->size = sizeof(struct hpi_response_header);
1807 goto err;
1808 }
1809
1810 if (phr->error != 0) /* something failed in the DSP */
1811 goto err;
1812
1813 switch (phm->function) {
1814 case HPI_OSTREAM_WRITE:
1815 case HPI_ISTREAM_ANC_WRITE:
1816 error = hpi6000_send_data(pao, dsp_index, phm, phr);
1817 break;
1818 case HPI_ISTREAM_READ:
1819 case HPI_OSTREAM_ANC_READ:
1820 error = hpi6000_get_data(pao, dsp_index, phm, phr);
1821 break;
1822 case HPI_ADAPTER_GET_ASSERT:
1823 phr->u.a.adapter_index = 0; /* dsp 0 default */
1824 if (num_dsp == 2) {
1825 if (!phr->u.a.adapter_type) {
1826 /* no assert from dsp 0, check dsp 1 */
1827 error = hpi6000_message_response_sequence(pao,
1828 1, phm, phr);
1829 phr->u.a.adapter_index = 1;
1830 }
1831 }
1832 }
1833
1834 if (error)
1835 phr->error = error;
1836
1837err:
1838 hpios_dsplock_unlock(pao);
1839 return;
1840}
diff --git a/sound/pci/asihpi/hpi6000.h b/sound/pci/asihpi/hpi6000.h
new file mode 100644
index 00000000000..4c7d507c0ec
--- /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 00000000000..5e88c1fc2b9
--- /dev/null
+++ b/sound/pci/asihpi/hpi6205.c
@@ -0,0 +1,2331 @@
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 = kzalloc(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
492 ao.pci = *phm->u.s.resource.r.pci;
493 err = create_adapter_obj(&ao, &os_error_code);
494 if (!err)
495 err = hpi_add_adapter(&ao);
496 if (err) {
497 phr->u.s.data = os_error_code;
498 delete_adapter_obj(&ao);
499 phr->error = err;
500 return;
501 }
502
503 phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
504 phr->u.s.adapter_index = ao.index;
505 phr->u.s.num_adapters++;
506 phr->error = 0;
507}
508
509/** delete an adapter - required by WDM driver */
510static void subsys_delete_adapter(struct hpi_message *phm,
511 struct hpi_response *phr)
512{
513 struct hpi_adapter_obj *pao;
514 struct hpi_hw_obj *phw;
515
516 pao = hpi_find_adapter(phm->adapter_index);
517 if (!pao) {
518 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
519 return;
520 }
521 phw = (struct hpi_hw_obj *)pao->priv;
522 /* reset adapter h/w */
523 /* Reset C6713 #1 */
524 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
525 /* reset C6205 */
526 iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);
527
528 delete_adapter_obj(pao);
529 phr->error = 0;
530}
531
532/** Create adapter object
533 allocate buffers, bootload DSPs, initialise control cache
534*/
535static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
536 u32 *pos_error_code)
537{
538 struct hpi_hw_obj *phw = pao->priv;
539 struct bus_master_interface *interface;
540 u32 phys_addr;
541#ifndef HPI6205_NO_HSR_POLL
542 u32 time_out = HPI6205_TIMEOUT;
543 u32 temp1;
544#endif
545 int i;
546 u16 err;
547
548 /* init error reporting */
549 pao->dsp_crashed = 0;
550
551 for (i = 0; i < HPI_MAX_STREAMS; i++)
552 phw->flag_outstream_just_reset[i] = 1;
553
554 /* The C6205 memory area 1 is 8Mbyte window into DSP registers */
555 phw->prHSR =
556 pao->pci.ap_mem_base[1] +
557 C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]);
558 phw->prHDCR =
559 pao->pci.ap_mem_base[1] +
560 C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]);
561 phw->prDSPP =
562 pao->pci.ap_mem_base[1] +
563 C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]);
564
565 pao->has_control_cache = 0;
566
567 if (hpios_locked_mem_alloc(&phw->h_locked_mem,
568 sizeof(struct bus_master_interface),
569 pao->pci.p_os_data))
570 phw->p_interface_buffer = NULL;
571 else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,
572 (void *)&phw->p_interface_buffer))
573 phw->p_interface_buffer = NULL;
574
575 HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n",
576 phw->p_interface_buffer);
577
578 if (phw->p_interface_buffer) {
579 memset((void *)phw->p_interface_buffer, 0,
580 sizeof(struct bus_master_interface));
581 phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN;
582 }
583
584 err = adapter_boot_load_dsp(pao, pos_error_code);
585 if (err)
586 /* no need to clean up as SubSysCreateAdapter */
587 /* calls DeleteAdapter on error. */
588 return err;
589
590 HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
591
592 /* allow boot load even if mem alloc wont work */
593 if (!phw->p_interface_buffer)
594 return hpi6205_error(0, HPI_ERROR_MEMORY_ALLOC);
595
596 interface = phw->p_interface_buffer;
597
598#ifndef HPI6205_NO_HSR_POLL
599 /* wait for first interrupt indicating the DSP init is done */
600 time_out = HPI6205_TIMEOUT * 10;
601 temp1 = 0;
602 while (((temp1 & C6205_HSR_INTSRC) == 0) && --time_out)
603 temp1 = ioread32(phw->prHSR);
604
605 if (temp1 & C6205_HSR_INTSRC)
606 HPI_DEBUG_LOG(INFO,
607 "interrupt confirming DSP code running OK\n");
608 else {
609 HPI_DEBUG_LOG(ERROR,
610 "timed out waiting for interrupt "
611 "confirming DSP code running\n");
612 return hpi6205_error(0, HPI6205_ERROR_6205_NO_IRQ);
613 }
614
615 /* reset the interrupt */
616 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
617#endif
618
619 /* make sure the DSP has started ok */
620 if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {
621 HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");
622 return hpi6205_error(0, HPI6205_ERROR_6205_INIT_FAILED);
623 }
624 /* Note that *pao, *phw are zeroed after allocation,
625 * so pointers and flags are NULL by default.
626 * Allocate bus mastering control cache buffer and tell the DSP about it
627 */
628 if (interface->control_cache.number_of_controls) {
629 void *p_control_cache_virtual;
630
631 err = hpios_locked_mem_alloc(&phw->h_control_cache,
632 interface->control_cache.size_in_bytes,
633 pao->pci.p_os_data);
634 if (!err)
635 err = hpios_locked_mem_get_virt_addr(&phw->
636 h_control_cache, &p_control_cache_virtual);
637 if (!err) {
638 memset(p_control_cache_virtual, 0,
639 interface->control_cache.size_in_bytes);
640
641 phw->p_cache =
642 hpi_alloc_control_cache(interface->
643 control_cache.number_of_controls,
644 interface->control_cache.size_in_bytes,
645 (struct hpi_control_cache_info *)
646 p_control_cache_virtual);
647 }
648 if (!err) {
649 err = hpios_locked_mem_get_phys_addr(&phw->
650 h_control_cache, &phys_addr);
651 interface->control_cache.physical_address32 =
652 phys_addr;
653 }
654
655 if (!err)
656 pao->has_control_cache = 1;
657 else {
658 if (hpios_locked_mem_valid(&phw->h_control_cache))
659 hpios_locked_mem_free(&phw->h_control_cache);
660 pao->has_control_cache = 0;
661 }
662 }
663 /* allocate bus mastering async buffer and tell the DSP about it */
664 if (interface->async_buffer.b.size) {
665 err = hpios_locked_mem_alloc(&phw->h_async_event_buffer,
666 interface->async_buffer.b.size *
667 sizeof(struct hpi_async_event), pao->pci.p_os_data);
668 if (!err)
669 err = hpios_locked_mem_get_virt_addr
670 (&phw->h_async_event_buffer, (void *)
671 &phw->p_async_event_buffer);
672 if (!err)
673 memset((void *)phw->p_async_event_buffer, 0,
674 interface->async_buffer.b.size *
675 sizeof(struct hpi_async_event));
676 if (!err) {
677 err = hpios_locked_mem_get_phys_addr
678 (&phw->h_async_event_buffer, &phys_addr);
679 interface->async_buffer.physical_address32 =
680 phys_addr;
681 }
682 if (err) {
683 if (hpios_locked_mem_valid(&phw->
684 h_async_event_buffer)) {
685 hpios_locked_mem_free
686 (&phw->h_async_event_buffer);
687 phw->p_async_event_buffer = NULL;
688 }
689 }
690 }
691 send_dsp_command(phw, H620_HIF_IDLE);
692
693 {
694 struct hpi_message hM;
695 struct hpi_response hR;
696 u32 max_streams;
697
698 HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
699 memset(&hM, 0, sizeof(hM));
700 hM.type = HPI_TYPE_MESSAGE;
701 hM.size = sizeof(hM);
702 hM.object = HPI_OBJ_ADAPTER;
703 hM.function = HPI_ADAPTER_GET_INFO;
704 hM.adapter_index = 0;
705 memset(&hR, 0, sizeof(hR));
706 hR.size = sizeof(hR);
707
708 err = message_response_sequence(pao, &hM, &hR);
709 if (err) {
710 HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
711 err);
712 return err;
713 }
714 if (hR.error)
715 return hR.error;
716
717 pao->adapter_type = hR.u.a.adapter_type;
718 pao->index = hR.u.a.adapter_index;
719
720 max_streams = hR.u.a.num_outstreams + hR.u.a.num_instreams;
721
722 hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams,
723 65536, pao->pci.p_os_data);
724
725 HPI_DEBUG_LOG(VERBOSE,
726 "got adapter info type %x index %d serial %d\n",
727 hR.u.a.adapter_type, hR.u.a.adapter_index,
728 hR.u.a.serial_number);
729 }
730
731 pao->open = 0; /* upon creation the adapter is closed */
732
733 HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
734 return 0;
735}
736
737/** Free memory areas allocated by adapter
738 * this routine is called from SubSysDeleteAdapter,
739 * and SubSysCreateAdapter if duplicate index
740*/
741static void delete_adapter_obj(struct hpi_adapter_obj *pao)
742{
743 struct hpi_hw_obj *phw;
744 int i;
745
746 phw = pao->priv;
747
748 if (hpios_locked_mem_valid(&phw->h_async_event_buffer)) {
749 hpios_locked_mem_free(&phw->h_async_event_buffer);
750 phw->p_async_event_buffer = NULL;
751 }
752
753 if (hpios_locked_mem_valid(&phw->h_control_cache)) {
754 hpios_locked_mem_free(&phw->h_control_cache);
755 hpi_free_control_cache(phw->p_cache);
756 }
757
758 if (hpios_locked_mem_valid(&phw->h_locked_mem)) {
759 hpios_locked_mem_free(&phw->h_locked_mem);
760 phw->p_interface_buffer = NULL;
761 }
762
763 for (i = 0; i < HPI_MAX_STREAMS; i++)
764 if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) {
765 hpios_locked_mem_free(&phw->instream_host_buffers[i]);
766 /*?phw->InStreamHostBuffers[i] = NULL; */
767 phw->instream_host_buffer_size[i] = 0;
768 }
769
770 for (i = 0; i < HPI_MAX_STREAMS; i++)
771 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) {
772 hpios_locked_mem_free(&phw->outstream_host_buffers
773 [i]);
774 phw->outstream_host_buffer_size[i] = 0;
775 }
776
777 hpios_locked_mem_unprepare(pao->pci.p_os_data);
778
779 hpi_delete_adapter(pao);
780 kfree(phw);
781}
782
783/*****************************************************************************/
784/* OutStream Host buffer functions */
785
786/** Allocate or attach buffer for busmastering
787*/
788static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
789 struct hpi_message *phm, struct hpi_response *phr)
790{
791 u16 err = 0;
792 u32 command = phm->u.d.u.buffer.command;
793 struct hpi_hw_obj *phw = pao->priv;
794 struct bus_master_interface *interface = phw->p_interface_buffer;
795
796 hpi_init_response(phr, phm->object, phm->function, 0);
797
798 if (command == HPI_BUFFER_CMD_EXTERNAL
799 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
800 /* ALLOC phase, allocate a buffer with power of 2 size,
801 get its bus address for PCI bus mastering
802 */
803 phm->u.d.u.buffer.buffer_size =
804 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
805 /* return old size and allocated size,
806 so caller can detect change */
807 phr->u.d.u.stream_info.data_available =
808 phw->outstream_host_buffer_size[phm->obj_index];
809 phr->u.d.u.stream_info.buffer_size =
810 phm->u.d.u.buffer.buffer_size;
811
812 if (phw->outstream_host_buffer_size[phm->obj_index] ==
813 phm->u.d.u.buffer.buffer_size) {
814 /* Same size, no action required */
815 return;
816 }
817
818 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
819 obj_index]))
820 hpios_locked_mem_free(&phw->outstream_host_buffers
821 [phm->obj_index]);
822
823 err = hpios_locked_mem_alloc(&phw->outstream_host_buffers
824 [phm->obj_index], phm->u.d.u.buffer.buffer_size,
825 pao->pci.p_os_data);
826
827 if (err) {
828 phr->error = HPI_ERROR_INVALID_DATASIZE;
829 phw->outstream_host_buffer_size[phm->obj_index] = 0;
830 return;
831 }
832
833 err = hpios_locked_mem_get_phys_addr
834 (&phw->outstream_host_buffers[phm->obj_index],
835 &phm->u.d.u.buffer.pci_address);
836 /* get the phys addr into msg for single call alloc caller
837 * needs to do this for split alloc (or use the same message)
838 * return the phy address for split alloc in the respose too
839 */
840 phr->u.d.u.stream_info.auxiliary_data_available =
841 phm->u.d.u.buffer.pci_address;
842
843 if (err) {
844 hpios_locked_mem_free(&phw->outstream_host_buffers
845 [phm->obj_index]);
846 phw->outstream_host_buffer_size[phm->obj_index] = 0;
847 phr->error = HPI_ERROR_MEMORY_ALLOC;
848 return;
849 }
850 }
851
852 if (command == HPI_BUFFER_CMD_EXTERNAL
853 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
854 /* GRANT phase. Set up the BBM status, tell the DSP about
855 the buffer so it can start using BBM.
856 */
857 struct hpi_hostbuffer_status *status;
858
859 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
860 buffer_size - 1)) {
861 HPI_DEBUG_LOG(ERROR,
862 "buffer size must be 2^N not %d\n",
863 phm->u.d.u.buffer.buffer_size);
864 phr->error = HPI_ERROR_INVALID_DATASIZE;
865 return;
866 }
867 phw->outstream_host_buffer_size[phm->obj_index] =
868 phm->u.d.u.buffer.buffer_size;
869 status = &interface->outstream_host_buffer_status[phm->
870 obj_index];
871 status->samples_processed = 0;
872 status->stream_state = HPI_STATE_STOPPED;
873 status->dSP_index = 0;
874 status->host_index = status->dSP_index;
875 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
876
877 hw_message(pao, phm, phr);
878
879 if (phr->error
880 && hpios_locked_mem_valid(&phw->
881 outstream_host_buffers[phm->obj_index])) {
882 hpios_locked_mem_free(&phw->outstream_host_buffers
883 [phm->obj_index]);
884 phw->outstream_host_buffer_size[phm->obj_index] = 0;
885 }
886 }
887}
888
889static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao,
890 struct hpi_message *phm, struct hpi_response *phr)
891{
892 struct hpi_hw_obj *phw = pao->priv;
893 struct bus_master_interface *interface = phw->p_interface_buffer;
894 struct hpi_hostbuffer_status *status;
895 u8 *p_bbm_data;
896
897 if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
898 obj_index])) {
899 if (hpios_locked_mem_get_virt_addr(&phw->
900 outstream_host_buffers[phm->obj_index],
901 (void *)&p_bbm_data)) {
902 phr->error = HPI_ERROR_INVALID_OPERATION;
903 return;
904 }
905 status = &interface->outstream_host_buffer_status[phm->
906 obj_index];
907 hpi_init_response(phr, HPI_OBJ_OSTREAM,
908 HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0);
909 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
910 phr->u.d.u.hostbuffer_info.p_status = status;
911 } else {
912 hpi_init_response(phr, HPI_OBJ_OSTREAM,
913 HPI_OSTREAM_HOSTBUFFER_GET_INFO,
914 HPI_ERROR_INVALID_OPERATION);
915 }
916}
917
918static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
919 struct hpi_message *phm, struct hpi_response *phr)
920{
921 struct hpi_hw_obj *phw = pao->priv;
922 u32 command = phm->u.d.u.buffer.command;
923
924 if (phw->outstream_host_buffer_size[phm->obj_index]) {
925 if (command == HPI_BUFFER_CMD_EXTERNAL
926 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
927 phw->outstream_host_buffer_size[phm->obj_index] = 0;
928 hw_message(pao, phm, phr);
929 /* Tell adapter to stop using the host buffer. */
930 }
931 if (command == HPI_BUFFER_CMD_EXTERNAL
932 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
933 hpios_locked_mem_free(&phw->outstream_host_buffers
934 [phm->obj_index]);
935 }
936 /* Should HPI_ERROR_INVALID_OPERATION be returned
937 if no host buffer is allocated? */
938 else
939 hpi_init_response(phr, HPI_OBJ_OSTREAM,
940 HPI_OSTREAM_HOSTBUFFER_FREE, 0);
941
942}
943
944static long outstream_get_space_available(struct hpi_hostbuffer_status
945 *status)
946{
947 return status->size_in_bytes - ((long)(status->host_index) -
948 (long)(status->dSP_index));
949}
950
951static void outstream_write(struct hpi_adapter_obj *pao,
952 struct hpi_message *phm, struct hpi_response *phr)
953{
954 struct hpi_hw_obj *phw = pao->priv;
955 struct bus_master_interface *interface = phw->p_interface_buffer;
956 struct hpi_hostbuffer_status *status;
957 long space_available;
958
959 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
960 /* there is no BBM buffer, write via message */
961 hw_message(pao, phm, phr);
962 return;
963 }
964
965 hpi_init_response(phr, phm->object, phm->function, 0);
966 status = &interface->outstream_host_buffer_status[phm->obj_index];
967
968 if (phw->flag_outstream_just_reset[phm->obj_index]) {
969 /* Format can only change after reset. Must tell DSP. */
970 u16 function = phm->function;
971 phw->flag_outstream_just_reset[phm->obj_index] = 0;
972 phm->function = HPI_OSTREAM_SET_FORMAT;
973 hw_message(pao, phm, phr); /* send the format to the DSP */
974 phm->function = function;
975 if (phr->error)
976 return;
977 }
978#if 1
979 if (phw->flag_outstream_just_reset[phm->obj_index]) {
980 /* First OutStremWrite() call following reset will write data to the
981 adapter's buffers, reducing delay before stream can start
982 */
983 int partial_write = 0;
984 unsigned int original_size = 0;
985
986 /* Send the first buffer to the DSP the old way. */
987 /* Limit size of first transfer - */
988 /* expect that this will not usually be triggered. */
989 if (phm->u.d.u.data.data_size > HPI6205_SIZEOF_DATA) {
990 partial_write = 1;
991 original_size = phm->u.d.u.data.data_size;
992 phm->u.d.u.data.data_size = HPI6205_SIZEOF_DATA;
993 }
994 /* write it */
995 phm->function = HPI_OSTREAM_WRITE;
996 hw_message(pao, phm, phr);
997 /* update status information that the DSP would typically
998 * update (and will update next time the DSP
999 * buffer update task reads data from the host BBM buffer)
1000 */
1001 status->auxiliary_data_available = phm->u.d.u.data.data_size;
1002 status->host_index += phm->u.d.u.data.data_size;
1003 status->dSP_index += phm->u.d.u.data.data_size;
1004
1005 /* if we did a full write, we can return from here. */
1006 if (!partial_write)
1007 return;
1008
1009 /* tweak buffer parameters and let the rest of the */
1010 /* buffer land in internal BBM buffer */
1011 phm->u.d.u.data.data_size =
1012 original_size - HPI6205_SIZEOF_DATA;
1013 phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA;
1014 }
1015#endif
1016
1017 space_available = outstream_get_space_available(status);
1018 if (space_available < (long)phm->u.d.u.data.data_size) {
1019 phr->error = HPI_ERROR_INVALID_DATASIZE;
1020 return;
1021 }
1022
1023 /* HostBuffers is used to indicate host buffer is internally allocated.
1024 otherwise, assumed external, data written externally */
1025 if (phm->u.d.u.data.pb_data
1026 && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
1027 obj_index])) {
1028 u8 *p_bbm_data;
1029 long l_first_write;
1030 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
1031
1032 if (hpios_locked_mem_get_virt_addr(&phw->
1033 outstream_host_buffers[phm->obj_index],
1034 (void *)&p_bbm_data)) {
1035 phr->error = HPI_ERROR_INVALID_OPERATION;
1036 return;
1037 }
1038
1039 /* either all data,
1040 or enough to fit from current to end of BBM buffer */
1041 l_first_write =
1042 min(phm->u.d.u.data.data_size,
1043 status->size_in_bytes -
1044 (status->host_index & (status->size_in_bytes - 1)));
1045
1046 memcpy(p_bbm_data +
1047 (status->host_index & (status->size_in_bytes - 1)),
1048 p_app_data, l_first_write);
1049 /* remaining data if any */
1050 memcpy(p_bbm_data, p_app_data + l_first_write,
1051 phm->u.d.u.data.data_size - l_first_write);
1052 }
1053 status->host_index += phm->u.d.u.data.data_size;
1054}
1055
1056static void outstream_get_info(struct hpi_adapter_obj *pao,
1057 struct hpi_message *phm, struct hpi_response *phr)
1058{
1059 struct hpi_hw_obj *phw = pao->priv;
1060 struct bus_master_interface *interface = phw->p_interface_buffer;
1061 struct hpi_hostbuffer_status *status;
1062
1063 if (!phw->outstream_host_buffer_size[phm->obj_index]) {
1064 hw_message(pao, phm, phr);
1065 return;
1066 }
1067
1068 hpi_init_response(phr, phm->object, phm->function, 0);
1069
1070 status = &interface->outstream_host_buffer_status[phm->obj_index];
1071
1072 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1073 phr->u.d.u.stream_info.samples_transferred =
1074 status->samples_processed;
1075 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1076 phr->u.d.u.stream_info.data_available =
1077 status->size_in_bytes - outstream_get_space_available(status);
1078 phr->u.d.u.stream_info.auxiliary_data_available =
1079 status->auxiliary_data_available;
1080}
1081
1082static void outstream_start(struct hpi_adapter_obj *pao,
1083 struct hpi_message *phm, struct hpi_response *phr)
1084{
1085 hw_message(pao, phm, phr);
1086}
1087
1088static void outstream_reset(struct hpi_adapter_obj *pao,
1089 struct hpi_message *phm, struct hpi_response *phr)
1090{
1091 struct hpi_hw_obj *phw = pao->priv;
1092 phw->flag_outstream_just_reset[phm->obj_index] = 1;
1093 hw_message(pao, phm, phr);
1094}
1095
1096static void outstream_open(struct hpi_adapter_obj *pao,
1097 struct hpi_message *phm, struct hpi_response *phr)
1098{
1099 outstream_reset(pao, phm, phr);
1100}
1101
1102/*****************************************************************************/
1103/* InStream Host buffer functions */
1104
1105static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
1106 struct hpi_message *phm, struct hpi_response *phr)
1107{
1108 u16 err = 0;
1109 u32 command = phm->u.d.u.buffer.command;
1110 struct hpi_hw_obj *phw = pao->priv;
1111 struct bus_master_interface *interface = phw->p_interface_buffer;
1112
1113 hpi_init_response(phr, phm->object, phm->function, 0);
1114
1115 if (command == HPI_BUFFER_CMD_EXTERNAL
1116 || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) {
1117
1118 phm->u.d.u.buffer.buffer_size =
1119 roundup_pow_of_two(phm->u.d.u.buffer.buffer_size);
1120 phr->u.d.u.stream_info.data_available =
1121 phw->instream_host_buffer_size[phm->obj_index];
1122 phr->u.d.u.stream_info.buffer_size =
1123 phm->u.d.u.buffer.buffer_size;
1124
1125 if (phw->instream_host_buffer_size[phm->obj_index] ==
1126 phm->u.d.u.buffer.buffer_size) {
1127 /* Same size, no action required */
1128 return;
1129 }
1130
1131 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1132 obj_index]))
1133 hpios_locked_mem_free(&phw->instream_host_buffers
1134 [phm->obj_index]);
1135
1136 err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->
1137 obj_index], phm->u.d.u.buffer.buffer_size,
1138 pao->pci.p_os_data);
1139
1140 if (err) {
1141 phr->error = HPI_ERROR_INVALID_DATASIZE;
1142 phw->instream_host_buffer_size[phm->obj_index] = 0;
1143 return;
1144 }
1145
1146 err = hpios_locked_mem_get_phys_addr
1147 (&phw->instream_host_buffers[phm->obj_index],
1148 &phm->u.d.u.buffer.pci_address);
1149 /* get the phys addr into msg for single call alloc. Caller
1150 needs to do this for split alloc so return the phy address */
1151 phr->u.d.u.stream_info.auxiliary_data_available =
1152 phm->u.d.u.buffer.pci_address;
1153 if (err) {
1154 hpios_locked_mem_free(&phw->instream_host_buffers
1155 [phm->obj_index]);
1156 phw->instream_host_buffer_size[phm->obj_index] = 0;
1157 phr->error = HPI_ERROR_MEMORY_ALLOC;
1158 return;
1159 }
1160 }
1161
1162 if (command == HPI_BUFFER_CMD_EXTERNAL
1163 || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) {
1164 struct hpi_hostbuffer_status *status;
1165
1166 if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
1167 buffer_size - 1)) {
1168 HPI_DEBUG_LOG(ERROR,
1169 "buffer size must be 2^N not %d\n",
1170 phm->u.d.u.buffer.buffer_size);
1171 phr->error = HPI_ERROR_INVALID_DATASIZE;
1172 return;
1173 }
1174
1175 phw->instream_host_buffer_size[phm->obj_index] =
1176 phm->u.d.u.buffer.buffer_size;
1177 status = &interface->instream_host_buffer_status[phm->
1178 obj_index];
1179 status->samples_processed = 0;
1180 status->stream_state = HPI_STATE_STOPPED;
1181 status->dSP_index = 0;
1182 status->host_index = status->dSP_index;
1183 status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
1184
1185 hw_message(pao, phm, phr);
1186 if (phr->error
1187 && hpios_locked_mem_valid(&phw->
1188 instream_host_buffers[phm->obj_index])) {
1189 hpios_locked_mem_free(&phw->instream_host_buffers
1190 [phm->obj_index]);
1191 phw->instream_host_buffer_size[phm->obj_index] = 0;
1192 }
1193 }
1194}
1195
1196static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao,
1197 struct hpi_message *phm, struct hpi_response *phr)
1198{
1199 struct hpi_hw_obj *phw = pao->priv;
1200 struct bus_master_interface *interface = phw->p_interface_buffer;
1201 struct hpi_hostbuffer_status *status;
1202 u8 *p_bbm_data;
1203
1204 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1205 obj_index])) {
1206 if (hpios_locked_mem_get_virt_addr(&phw->
1207 instream_host_buffers[phm->obj_index],
1208 (void *)&p_bbm_data)) {
1209 phr->error = HPI_ERROR_INVALID_OPERATION;
1210 return;
1211 }
1212 status = &interface->instream_host_buffer_status[phm->
1213 obj_index];
1214 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1215 HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0);
1216 phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data;
1217 phr->u.d.u.hostbuffer_info.p_status = status;
1218 } else {
1219 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1220 HPI_ISTREAM_HOSTBUFFER_GET_INFO,
1221 HPI_ERROR_INVALID_OPERATION);
1222 }
1223}
1224
1225static void instream_host_buffer_free(struct hpi_adapter_obj *pao,
1226 struct hpi_message *phm, struct hpi_response *phr)
1227{
1228 struct hpi_hw_obj *phw = pao->priv;
1229 u32 command = phm->u.d.u.buffer.command;
1230
1231 if (phw->instream_host_buffer_size[phm->obj_index]) {
1232 if (command == HPI_BUFFER_CMD_EXTERNAL
1233 || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) {
1234 phw->instream_host_buffer_size[phm->obj_index] = 0;
1235 hw_message(pao, phm, phr);
1236 }
1237
1238 if (command == HPI_BUFFER_CMD_EXTERNAL
1239 || command == HPI_BUFFER_CMD_INTERNAL_FREE)
1240 hpios_locked_mem_free(&phw->instream_host_buffers
1241 [phm->obj_index]);
1242
1243 } else {
1244 /* Should HPI_ERROR_INVALID_OPERATION be returned
1245 if no host buffer is allocated? */
1246 hpi_init_response(phr, HPI_OBJ_ISTREAM,
1247 HPI_ISTREAM_HOSTBUFFER_FREE, 0);
1248
1249 }
1250
1251}
1252
1253static void instream_start(struct hpi_adapter_obj *pao,
1254 struct hpi_message *phm, struct hpi_response *phr)
1255{
1256 hw_message(pao, phm, phr);
1257}
1258
1259static long instream_get_bytes_available(struct hpi_hostbuffer_status *status)
1260{
1261 return (long)(status->dSP_index) - (long)(status->host_index);
1262}
1263
1264static void instream_read(struct hpi_adapter_obj *pao,
1265 struct hpi_message *phm, struct hpi_response *phr)
1266{
1267 struct hpi_hw_obj *phw = pao->priv;
1268 struct bus_master_interface *interface = phw->p_interface_buffer;
1269 struct hpi_hostbuffer_status *status;
1270 long data_available;
1271 u8 *p_bbm_data;
1272 long l_first_read;
1273 u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
1274
1275 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1276 hw_message(pao, phm, phr);
1277 return;
1278 }
1279 hpi_init_response(phr, phm->object, phm->function, 0);
1280
1281 status = &interface->instream_host_buffer_status[phm->obj_index];
1282 data_available = instream_get_bytes_available(status);
1283 if (data_available < (long)phm->u.d.u.data.data_size) {
1284 phr->error = HPI_ERROR_INVALID_DATASIZE;
1285 return;
1286 }
1287
1288 if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm->
1289 obj_index])) {
1290 if (hpios_locked_mem_get_virt_addr(&phw->
1291 instream_host_buffers[phm->obj_index],
1292 (void *)&p_bbm_data)) {
1293 phr->error = HPI_ERROR_INVALID_OPERATION;
1294 return;
1295 }
1296
1297 /* either all data,
1298 or enough to fit from current to end of BBM buffer */
1299 l_first_read =
1300 min(phm->u.d.u.data.data_size,
1301 status->size_in_bytes -
1302 (status->host_index & (status->size_in_bytes - 1)));
1303
1304 memcpy(p_app_data,
1305 p_bbm_data +
1306 (status->host_index & (status->size_in_bytes - 1)),
1307 l_first_read);
1308 /* remaining data if any */
1309 memcpy(p_app_data + l_first_read, p_bbm_data,
1310 phm->u.d.u.data.data_size - l_first_read);
1311 }
1312 status->host_index += phm->u.d.u.data.data_size;
1313}
1314
1315static void instream_get_info(struct hpi_adapter_obj *pao,
1316 struct hpi_message *phm, struct hpi_response *phr)
1317{
1318 struct hpi_hw_obj *phw = pao->priv;
1319 struct bus_master_interface *interface = phw->p_interface_buffer;
1320 struct hpi_hostbuffer_status *status;
1321 if (!phw->instream_host_buffer_size[phm->obj_index]) {
1322 hw_message(pao, phm, phr);
1323 return;
1324 }
1325
1326 status = &interface->instream_host_buffer_status[phm->obj_index];
1327
1328 hpi_init_response(phr, phm->object, phm->function, 0);
1329
1330 phr->u.d.u.stream_info.state = (u16)status->stream_state;
1331 phr->u.d.u.stream_info.samples_transferred =
1332 status->samples_processed;
1333 phr->u.d.u.stream_info.buffer_size = status->size_in_bytes;
1334 phr->u.d.u.stream_info.data_available =
1335 instream_get_bytes_available(status);
1336 phr->u.d.u.stream_info.auxiliary_data_available =
1337 status->auxiliary_data_available;
1338}
1339
1340/*****************************************************************************/
1341/* LOW-LEVEL */
1342#define HPI6205_MAX_FILES_TO_LOAD 2
1343
1344static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
1345 u32 *pos_error_code)
1346{
1347 struct hpi_hw_obj *phw = pao->priv;
1348 struct dsp_code dsp_code;
1349 u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];
1350 u16 firmware_id = pao->pci.subsys_device_id;
1351 u32 temp;
1352 int dsp = 0, i = 0;
1353 u16 err = 0;
1354
1355 boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);
1356
1357 /* special cases where firmware_id != subsys ID */
1358 switch (firmware_id) {
1359 case HPI_ADAPTER_FAMILY_ASI(0x5000):
1360 boot_code_id[0] = firmware_id;
1361 firmware_id = 0;
1362 break;
1363 case HPI_ADAPTER_FAMILY_ASI(0x5300):
1364 case HPI_ADAPTER_FAMILY_ASI(0x5400):
1365 case HPI_ADAPTER_FAMILY_ASI(0x6300):
1366 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6400);
1367 break;
1368 case HPI_ADAPTER_FAMILY_ASI(0x5600):
1369 case HPI_ADAPTER_FAMILY_ASI(0x6500):
1370 firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
1371 break;
1372 }
1373 boot_code_id[1] = firmware_id;
1374
1375 /* reset DSP by writing a 1 to the WARMRESET bit */
1376 temp = C6205_HDCR_WARMRESET;
1377 iowrite32(temp, phw->prHDCR);
1378 hpios_delay_micro_seconds(1000);
1379
1380 /* check that PCI i/f was configured by EEPROM */
1381 temp = ioread32(phw->prHSR);
1382 if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=
1383 C6205_HSR_EEREAD)
1384 return hpi6205_error(0, HPI6205_ERROR_6205_EEPROM);
1385 temp |= 0x04;
1386 /* disable PINTA interrupt */
1387 iowrite32(temp, phw->prHSR);
1388
1389 /* check control register reports PCI boot mode */
1390 temp = ioread32(phw->prHDCR);
1391 if (!(temp & C6205_HDCR_PCIBOOT))
1392 return hpi6205_error(0, HPI6205_ERROR_6205_REG);
1393
1394 /* try writing a couple of numbers to the DSP page register */
1395 /* and reading them back. */
1396 temp = 1;
1397 iowrite32(temp, phw->prDSPP);
1398 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1399 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1400 temp = 2;
1401 iowrite32(temp, phw->prDSPP);
1402 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1403 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1404 temp = 3;
1405 iowrite32(temp, phw->prDSPP);
1406 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1407 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1408 /* reset DSP page to the correct number */
1409 temp = 0;
1410 iowrite32(temp, phw->prDSPP);
1411 if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
1412 return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
1413 phw->dsp_page = 0;
1414
1415 /* release 6713 from reset before 6205 is bootloaded.
1416 This ensures that the EMIF is inactive,
1417 and the 6713 HPI gets the correct bootmode etc
1418 */
1419 if (boot_code_id[1] != 0) {
1420 /* DSP 1 is a C6713 */
1421 /* CLKX0 <- '1' release the C6205 bootmode pulldowns */
1422 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002202);
1423 hpios_delay_micro_seconds(100);
1424 /* Reset the 6713 #1 - revB */
1425 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
1426
1427 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1428 boot_loader_read_mem32(pao, 0, 0);
1429
1430 hpios_delay_micro_seconds(100);
1431 /* Release C6713 from reset - revB */
1432 boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4);
1433 hpios_delay_micro_seconds(100);
1434 }
1435
1436 for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) {
1437 /* is there a DSP to load? */
1438 if (boot_code_id[dsp] == 0)
1439 continue;
1440
1441 err = boot_loader_config_emif(pao, dsp);
1442 if (err)
1443 return err;
1444
1445 err = boot_loader_test_internal_memory(pao, dsp);
1446 if (err)
1447 return err;
1448
1449 err = boot_loader_test_external_memory(pao, dsp);
1450 if (err)
1451 return err;
1452
1453 err = boot_loader_test_pld(pao, dsp);
1454 if (err)
1455 return err;
1456
1457 /* write the DSP code down into the DSPs memory */
1458 dsp_code.ps_dev = pao->pci.p_os_data;
1459 err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code,
1460 pos_error_code);
1461 if (err)
1462 return err;
1463
1464 while (1) {
1465 u32 length;
1466 u32 address;
1467 u32 type;
1468 u32 *pcode;
1469
1470 err = hpi_dsp_code_read_word(&dsp_code, &length);
1471 if (err)
1472 break;
1473 if (length == 0xFFFFFFFF)
1474 break; /* end of code */
1475
1476 err = hpi_dsp_code_read_word(&dsp_code, &address);
1477 if (err)
1478 break;
1479 err = hpi_dsp_code_read_word(&dsp_code, &type);
1480 if (err)
1481 break;
1482 err = hpi_dsp_code_read_block(length, &dsp_code,
1483 &pcode);
1484 if (err)
1485 break;
1486 for (i = 0; i < (int)length; i++) {
1487 err = boot_loader_write_mem32(pao, dsp,
1488 address, *pcode);
1489 if (err)
1490 break;
1491 /* dummy read every 4 words */
1492 /* for 6205 advisory 1.4.4 */
1493 if (i % 4 == 0)
1494 boot_loader_read_mem32(pao, dsp,
1495 address);
1496 pcode++;
1497 address += 4;
1498 }
1499
1500 }
1501 if (err) {
1502 hpi_dsp_code_close(&dsp_code);
1503 return err;
1504 }
1505
1506 /* verify code */
1507 hpi_dsp_code_rewind(&dsp_code);
1508 while (1) {
1509 u32 length = 0;
1510 u32 address = 0;
1511 u32 type = 0;
1512 u32 *pcode = NULL;
1513 u32 data = 0;
1514
1515 hpi_dsp_code_read_word(&dsp_code, &length);
1516 if (length == 0xFFFFFFFF)
1517 break; /* end of code */
1518
1519 hpi_dsp_code_read_word(&dsp_code, &address);
1520 hpi_dsp_code_read_word(&dsp_code, &type);
1521 hpi_dsp_code_read_block(length, &dsp_code, &pcode);
1522
1523 for (i = 0; i < (int)length; i++) {
1524 data = boot_loader_read_mem32(pao, dsp,
1525 address);
1526 if (data != *pcode) {
1527 err = 0;
1528 break;
1529 }
1530 pcode++;
1531 address += 4;
1532 }
1533 if (err)
1534 break;
1535 }
1536 hpi_dsp_code_close(&dsp_code);
1537 if (err)
1538 return err;
1539 }
1540
1541 /* After bootloading all DSPs, start DSP0 running
1542 * The DSP0 code will handle starting and synchronizing with its slaves
1543 */
1544 if (phw->p_interface_buffer) {
1545 /* we need to tell the card the physical PCI address */
1546 u32 physicalPC_iaddress;
1547 struct bus_master_interface *interface =
1548 phw->p_interface_buffer;
1549 u32 host_mailbox_address_on_dsp;
1550 u32 physicalPC_iaddress_verify = 0;
1551 int time_out = 10;
1552 /* set ack so we know when DSP is ready to go */
1553 /* (dwDspAck will be changed to HIF_RESET) */
1554 interface->dsp_ack = H620_HIF_UNKNOWN;
1555 wmb(); /* ensure ack is written before dsp writes back */
1556
1557 err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem,
1558 &physicalPC_iaddress);
1559
1560 /* locate the host mailbox on the DSP. */
1561 host_mailbox_address_on_dsp = 0x80000000;
1562 while ((physicalPC_iaddress != physicalPC_iaddress_verify)
1563 && time_out--) {
1564 err = boot_loader_write_mem32(pao, 0,
1565 host_mailbox_address_on_dsp,
1566 physicalPC_iaddress);
1567 physicalPC_iaddress_verify =
1568 boot_loader_read_mem32(pao, 0,
1569 host_mailbox_address_on_dsp);
1570 }
1571 }
1572 HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n");
1573 /* enable interrupts */
1574 temp = ioread32(phw->prHSR);
1575 temp &= ~(u32)C6205_HSR_INTAM;
1576 iowrite32(temp, phw->prHSR);
1577
1578 /* start code running... */
1579 temp = ioread32(phw->prHDCR);
1580 temp |= (u32)C6205_HDCR_DSPINT;
1581 iowrite32(temp, phw->prHDCR);
1582
1583 /* give the DSP 10ms to start up */
1584 hpios_delay_micro_seconds(10000);
1585 return err;
1586
1587}
1588
1589/*****************************************************************************/
1590/* Bootloader utility functions */
1591
1592static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
1593 u32 address)
1594{
1595 struct hpi_hw_obj *phw = pao->priv;
1596 u32 data = 0;
1597 __iomem u32 *p_data;
1598
1599 if (dsp_index == 0) {
1600 /* DSP 0 is always C6205 */
1601 if ((address >= 0x01800000) & (address < 0x02000000)) {
1602 /* BAR1 register access */
1603 p_data = pao->pci.ap_mem_base[1] +
1604 (address & 0x007fffff) /
1605 sizeof(*pao->pci.ap_mem_base[1]);
1606 /* HPI_DEBUG_LOG(WARNING,
1607 "BAR1 access %08x\n", dwAddress); */
1608 } else {
1609 u32 dw4M_page = address >> 22L;
1610 if (dw4M_page != phw->dsp_page) {
1611 phw->dsp_page = dw4M_page;
1612 /* *INDENT OFF* */
1613 iowrite32(phw->dsp_page, phw->prDSPP);
1614 /* *INDENT-ON* */
1615 }
1616 address &= 0x3fffff; /* address within 4M page */
1617 /* BAR0 memory access */
1618 p_data = pao->pci.ap_mem_base[0] +
1619 address / sizeof(u32);
1620 }
1621 data = ioread32(p_data);
1622 } else if (dsp_index == 1) {
1623 /* DSP 1 is a C6713 */
1624 u32 lsb;
1625 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1626 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1627 lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR);
1628 data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR);
1629 data = (data << 16) | (lsb & 0xFFFF);
1630 }
1631 return data;
1632}
1633
1634static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index,
1635 u32 address, u32 data)
1636{
1637 struct hpi_hw_obj *phw = pao->priv;
1638 u16 err = 0;
1639 __iomem u32 *p_data;
1640 /* u32 dwVerifyData=0; */
1641
1642 if (dsp_index == 0) {
1643 /* DSP 0 is always C6205 */
1644 if ((address >= 0x01800000) & (address < 0x02000000)) {
1645 /* BAR1 - DSP register access using */
1646 /* Non-prefetchable PCI access */
1647 p_data = pao->pci.ap_mem_base[1] +
1648 (address & 0x007fffff) /
1649 sizeof(*pao->pci.ap_mem_base[1]);
1650 } else {
1651 /* BAR0 access - all of DSP memory using */
1652 /* pre-fetchable PCI access */
1653 u32 dw4M_page = address >> 22L;
1654 if (dw4M_page != phw->dsp_page) {
1655 phw->dsp_page = dw4M_page;
1656 /* *INDENT-OFF* */
1657 iowrite32(phw->dsp_page, phw->prDSPP);
1658 /* *INDENT-ON* */
1659 }
1660 address &= 0x3fffff; /* address within 4M page */
1661 p_data = pao->pci.ap_mem_base[0] +
1662 address / sizeof(u32);
1663 }
1664 iowrite32(data, p_data);
1665 } else if (dsp_index == 1) {
1666 /* DSP 1 is a C6713 */
1667 boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address);
1668 boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16);
1669
1670 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1671 boot_loader_read_mem32(pao, 0, 0);
1672
1673 boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data);
1674 boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16);
1675
1676 /* dummy read every 4 words for 6205 advisory 1.4.4 */
1677 boot_loader_read_mem32(pao, 0, 0);
1678 } else
1679 err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1680 return err;
1681}
1682
1683static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
1684{
1685 u16 err = 0;
1686
1687 if (dsp_index == 0) {
1688 u32 setting;
1689
1690 /* DSP 0 is always C6205 */
1691
1692 /* Set the EMIF */
1693 /* memory map of C6205 */
1694 /* 00000000-0000FFFF 16Kx32 internal program */
1695 /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */
1696
1697 /* EMIF config */
1698 /*------------ */
1699 /* Global EMIF control */
1700 boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779);
1701#define WS_OFS 28
1702#define WST_OFS 22
1703#define WH_OFS 20
1704#define RS_OFS 16
1705#define RST_OFS 8
1706#define MTYPE_OFS 4
1707#define RH_OFS 0
1708
1709 /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */
1710 setting = 0x00000030;
1711 boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
1712 if (setting != boot_loader_read_mem32(pao, dsp_index,
1713 0x01800008))
1714 return hpi6205_error(dsp_index,
1715 HPI6205_ERROR_DSP_EMIF);
1716
1717 /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
1718 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1719 /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */
1720 /* WST should be 71, but 63 is max possible */
1721 setting =
1722 (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) |
1723 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1724 (2L << MTYPE_OFS);
1725 boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
1726 if (setting != boot_loader_read_mem32(pao, dsp_index,
1727 0x01800004))
1728 return hpi6205_error(dsp_index,
1729 HPI6205_ERROR_DSP_EMIF);
1730
1731 /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
1732 /* which occupies D15..0. 6713 starts at 27MHz, so need */
1733 /* plenty of wait states */
1734 setting =
1735 (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) |
1736 (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) |
1737 (2L << MTYPE_OFS);
1738 boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
1739 if (setting != boot_loader_read_mem32(pao, dsp_index,
1740 0x01800010))
1741 return hpi6205_error(dsp_index,
1742 HPI6205_ERROR_DSP_EMIF);
1743
1744 /* EMIF CE3 setup - 32 bit async. */
1745 /* This is the PLD on the ASI5000 cards only */
1746 setting =
1747 (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) |
1748 (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) |
1749 (2L << MTYPE_OFS);
1750 boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
1751 if (setting != boot_loader_read_mem32(pao, dsp_index,
1752 0x01800014))
1753 return hpi6205_error(dsp_index,
1754 HPI6205_ERROR_DSP_EMIF);
1755
1756 /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
1757 /* need to use this else DSP code crashes? */
1758 boot_loader_write_mem32(pao, dsp_index, 0x01800018,
1759 0x07117000);
1760
1761 /* EMIF SDRAM Refresh Timing */
1762 /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */
1763 boot_loader_write_mem32(pao, dsp_index, 0x0180001C,
1764 0x00000410);
1765
1766 } else if (dsp_index == 1) {
1767 /* test access to the C6713s HPI registers */
1768 u32 write_data = 0, read_data = 0, i = 0;
1769
1770 /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */
1771 write_data = 1;
1772 boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data);
1773 boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data);
1774 /* C67 HPI is on lower 16bits of 32bit EMIF */
1775 read_data =
1776 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);
1777 if (write_data != read_data) {
1778 err = hpi6205_error(dsp_index,
1779 HPI6205_ERROR_C6713_HPIC);
1780 HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,
1781 read_data);
1782
1783 return err;
1784 }
1785 /* HPIA - walking ones test */
1786 write_data = 1;
1787 for (i = 0; i < 32; i++) {
1788 boot_loader_write_mem32(pao, 0, HPIAL_ADDR,
1789 write_data);
1790 boot_loader_write_mem32(pao, 0, HPIAH_ADDR,
1791 (write_data >> 16));
1792 read_data =
1793 0xFFFF & boot_loader_read_mem32(pao, 0,
1794 HPIAL_ADDR);
1795 read_data =
1796 read_data | ((0xFFFF &
1797 boot_loader_read_mem32(pao, 0,
1798 HPIAH_ADDR))
1799 << 16);
1800 if (read_data != write_data) {
1801 err = hpi6205_error(dsp_index,
1802 HPI6205_ERROR_C6713_HPIA);
1803 HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",
1804 write_data, read_data);
1805 return err;
1806 }
1807 write_data = write_data << 1;
1808 }
1809
1810 /* setup C67x PLL
1811 * ** C6713 datasheet says we cannot program PLL from HPI,
1812 * and indeed if we try to set the PLL multiply from the HPI,
1813 * the PLL does not seem to lock, so we enable the PLL and
1814 * use the default multiply of x 7, which for a 27MHz clock
1815 * gives a DSP speed of 189MHz
1816 */
1817 /* bypass PLL */
1818 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000);
1819 hpios_delay_micro_seconds(1000);
1820 /* EMIF = 189/3=63MHz */
1821 boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002);
1822 /* peri = 189/2 */
1823 boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001);
1824 /* cpu = 189/1 */
1825 boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000);
1826 hpios_delay_micro_seconds(1000);
1827 /* ** SGT test to take GPO3 high when we start the PLL */
1828 /* and low when the delay is completed */
1829 /* FSX0 <- '1' (GPO3) */
1830 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A);
1831 /* PLL not bypassed */
1832 boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001);
1833 hpios_delay_micro_seconds(1000);
1834 /* FSX0 <- '0' (GPO3) */
1835 boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02);
1836
1837 /* 6205 EMIF CE1 resetup - 32 bit async. */
1838 /* Now 6713 #1 is running at 189MHz can reduce waitstates */
1839 boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */
1840 (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) |
1841 (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) |
1842 (2L << MTYPE_OFS));
1843
1844 hpios_delay_micro_seconds(1000);
1845
1846 /* check that we can read one of the PLL registers */
1847 /* PLL should not be bypassed! */
1848 if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)
1849 != 0x0001) {
1850 err = hpi6205_error(dsp_index,
1851 HPI6205_ERROR_C6713_PLL);
1852 return err;
1853 }
1854 /* setup C67x EMIF (note this is the only use of
1855 BAR1 via BootLoader_WriteMem32) */
1856 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,
1857 0x000034A8);
1858 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,
1859 0x00000030);
1860 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,
1861 0x001BDF29);
1862 boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,
1863 0x47117000);
1864 boot_loader_write_mem32(pao, dsp_index,
1865 C6713_EMIF_SDRAMTIMING, 0x00000410);
1866
1867 hpios_delay_micro_seconds(1000);
1868 } else if (dsp_index == 2) {
1869 /* DSP 2 is a C6713 */
1870
1871 } else
1872 err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1873 return err;
1874}
1875
1876static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
1877 u32 start_address, u32 length)
1878{
1879 u32 i = 0, j = 0;
1880 u32 test_addr = 0;
1881 u32 test_data = 0, data = 0;
1882
1883 length = 1000;
1884
1885 /* for 1st word, test each bit in the 32bit word, */
1886 /* dwLength specifies number of 32bit words to test */
1887 /*for(i=0; i<dwLength; i++) */
1888 i = 0;
1889 {
1890 test_addr = start_address + i * 4;
1891 test_data = 0x00000001;
1892 for (j = 0; j < 32; j++) {
1893 boot_loader_write_mem32(pao, dsp_index, test_addr,
1894 test_data);
1895 data = boot_loader_read_mem32(pao, dsp_index,
1896 test_addr);
1897 if (data != test_data) {
1898 HPI_DEBUG_LOG(VERBOSE,
1899 "memtest error details "
1900 "%08x %08x %08x %i\n", test_addr,
1901 test_data, data, dsp_index);
1902 return 1; /* error */
1903 }
1904 test_data = test_data << 1;
1905 } /* for(j) */
1906 } /* for(i) */
1907
1908 /* for the next 100 locations test each location, leaving it as zero */
1909 /* write a zero to the next word in memory before we read */
1910 /* the previous write to make sure every memory location is unique */
1911 for (i = 0; i < 100; i++) {
1912 test_addr = start_address + i * 4;
1913 test_data = 0xA5A55A5A;
1914 boot_loader_write_mem32(pao, dsp_index, test_addr, test_data);
1915 boot_loader_write_mem32(pao, dsp_index, test_addr + 4, 0);
1916 data = boot_loader_read_mem32(pao, dsp_index, test_addr);
1917 if (data != test_data) {
1918 HPI_DEBUG_LOG(VERBOSE,
1919 "memtest error details "
1920 "%08x %08x %08x %i\n", test_addr, test_data,
1921 data, dsp_index);
1922 return 1; /* error */
1923 }
1924 /* leave location as zero */
1925 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1926 }
1927
1928 /* zero out entire memory block */
1929 for (i = 0; i < length; i++) {
1930 test_addr = start_address + i * 4;
1931 boot_loader_write_mem32(pao, dsp_index, test_addr, 0x0);
1932 }
1933 return 0;
1934}
1935
1936static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
1937 int dsp_index)
1938{
1939 int err = 0;
1940 if (dsp_index == 0) {
1941 /* DSP 0 is a C6205 */
1942 /* 64K prog mem */
1943 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1944 0x10000);
1945 if (!err)
1946 /* 64K data mem */
1947 err = boot_loader_test_memory(pao, dsp_index,
1948 0x80000000, 0x10000);
1949 } else if ((dsp_index == 1) || (dsp_index == 2)) {
1950 /* DSP 1&2 are a C6713 */
1951 /* 192K internal mem */
1952 err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
1953 0x30000);
1954 if (!err)
1955 /* 64K internal mem / L2 cache */
1956 err = boot_loader_test_memory(pao, dsp_index,
1957 0x00030000, 0x10000);
1958 } else
1959 return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1960
1961 if (err)
1962 return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_INTMEM);
1963 else
1964 return 0;
1965}
1966
1967static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
1968 int dsp_index)
1969{
1970 u32 dRAM_start_address = 0;
1971 u32 dRAM_size = 0;
1972
1973 if (dsp_index == 0) {
1974 /* only test for SDRAM if an ASI5000 card */
1975 if (pao->pci.subsys_device_id == 0x5000) {
1976 /* DSP 0 is always C6205 */
1977 dRAM_start_address = 0x00400000;
1978 dRAM_size = 0x200000;
1979 /*dwDRAMinc=1024; */
1980 } else
1981 return 0;
1982 } else if ((dsp_index == 1) || (dsp_index == 2)) {
1983 /* DSP 1 is a C6713 */
1984 dRAM_start_address = 0x80000000;
1985 dRAM_size = 0x200000;
1986 /*dwDRAMinc=1024; */
1987 } else
1988 return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
1989
1990 if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,
1991 dRAM_size))
1992 return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_EXTMEM);
1993 return 0;
1994}
1995
1996static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)
1997{
1998 u32 data = 0;
1999 if (dsp_index == 0) {
2000 /* only test for DSP0 PLD on ASI5000 card */
2001 if (pao->pci.subsys_device_id == 0x5000) {
2002 /* PLD is located at CE3=0x03000000 */
2003 data = boot_loader_read_mem32(pao, dsp_index,
2004 0x03000008);
2005 if ((data & 0xF) != 0x5)
2006 return hpi6205_error(dsp_index,
2007 HPI6205_ERROR_DSP_PLD);
2008 data = boot_loader_read_mem32(pao, dsp_index,
2009 0x0300000C);
2010 if ((data & 0xF) != 0xA)
2011 return hpi6205_error(dsp_index,
2012 HPI6205_ERROR_DSP_PLD);
2013 }
2014 } else if (dsp_index == 1) {
2015 /* DSP 1 is a C6713 */
2016 if (pao->pci.subsys_device_id == 0x8700) {
2017 /* PLD is located at CE1=0x90000000 */
2018 data = boot_loader_read_mem32(pao, dsp_index,
2019 0x90000010);
2020 if ((data & 0xFF) != 0xAA)
2021 return hpi6205_error(dsp_index,
2022 HPI6205_ERROR_DSP_PLD);
2023 /* 8713 - LED on */
2024 boot_loader_write_mem32(pao, dsp_index, 0x90000000,
2025 0x02);
2026 }
2027 }
2028 return 0;
2029}
2030
2031/** Transfer data to or from DSP
2032 nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA
2033*/
2034static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
2035 u32 data_size, int operation)
2036{
2037 struct hpi_hw_obj *phw = pao->priv;
2038 u32 data_transferred = 0;
2039 u16 err = 0;
2040#ifndef HPI6205_NO_HSR_POLL
2041 u32 time_out;
2042#endif
2043 u32 temp2;
2044 struct bus_master_interface *interface = phw->p_interface_buffer;
2045
2046 if (!p_data)
2047 return HPI_ERROR_INVALID_DATA_TRANSFER;
2048
2049 data_size &= ~3L; /* round data_size down to nearest 4 bytes */
2050
2051 /* make sure state is IDLE */
2052 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT))
2053 return HPI_ERROR_DSP_HARDWARE;
2054
2055 while (data_transferred < data_size) {
2056 u32 this_copy = data_size - data_transferred;
2057
2058 if (this_copy > HPI6205_SIZEOF_DATA)
2059 this_copy = HPI6205_SIZEOF_DATA;
2060
2061 if (operation == H620_HIF_SEND_DATA)
2062 memcpy((void *)&interface->u.b_data[0],
2063 &p_data[data_transferred], this_copy);
2064
2065 interface->transfer_size_in_bytes = this_copy;
2066
2067#ifdef HPI6205_NO_HSR_POLL
2068 /* DSP must change this back to nOperation */
2069 interface->dsp_ack = H620_HIF_IDLE;
2070#endif
2071
2072 send_dsp_command(phw, operation);
2073
2074#ifdef HPI6205_NO_HSR_POLL
2075 temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT);
2076 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2077 HPI6205_TIMEOUT - temp2, this_copy);
2078
2079 if (!temp2) {
2080 /* timed out */
2081 HPI_DEBUG_LOG(ERROR,
2082 "timed out waiting for " "state %d got %d\n",
2083 operation, interface->dsp_ack);
2084
2085 break;
2086 }
2087#else
2088 /* spin waiting on the result */
2089 time_out = HPI6205_TIMEOUT;
2090 temp2 = 0;
2091 while ((temp2 == 0) && time_out--) {
2092 /* give 16k bus mastering transfer time to happen */
2093 /*(16k / 132Mbytes/s = 122usec) */
2094 hpios_delay_micro_seconds(20);
2095 temp2 = ioread32(phw->prHSR);
2096 temp2 &= C6205_HSR_INTSRC;
2097 }
2098 HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
2099 HPI6205_TIMEOUT - time_out, this_copy);
2100 if (temp2 == C6205_HSR_INTSRC) {
2101 HPI_DEBUG_LOG(VERBOSE,
2102 "interrupt from HIF <data> OK\n");
2103 /*
2104 if(interface->dwDspAck != nOperation) {
2105 HPI_DEBUG_LOG(DEBUG("interface->dwDspAck=%d,
2106 expected %d \n",
2107 interface->dwDspAck,nOperation);
2108 }
2109 */
2110 }
2111/* need to handle this differently... */
2112 else {
2113 HPI_DEBUG_LOG(ERROR,
2114 "interrupt from HIF <data> BAD\n");
2115 err = HPI_ERROR_DSP_HARDWARE;
2116 }
2117
2118 /* reset the interrupt from the DSP */
2119 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2120#endif
2121 if (operation == H620_HIF_GET_DATA)
2122 memcpy(&p_data[data_transferred],
2123 (void *)&interface->u.b_data[0], this_copy);
2124
2125 data_transferred += this_copy;
2126 }
2127 if (interface->dsp_ack != operation)
2128 HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n",
2129 interface->dsp_ack, operation);
2130 /* err=HPI_ERROR_DSP_HARDWARE; */
2131
2132 send_dsp_command(phw, H620_HIF_IDLE);
2133
2134 return err;
2135}
2136
2137/* wait for up to timeout_us microseconds for the DSP
2138 to signal state by DMA into dwDspAck
2139*/
2140static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
2141{
2142 struct bus_master_interface *interface = phw->p_interface_buffer;
2143 int t = timeout_us / 4;
2144
2145 rmb(); /* ensure interface->dsp_ack is up to date */
2146 while ((interface->dsp_ack != state) && --t) {
2147 hpios_delay_micro_seconds(4);
2148 rmb(); /* DSP changes dsp_ack by DMA */
2149 }
2150
2151 /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */
2152 return t * 4;
2153}
2154
2155/* set the busmaster interface to cmd, then interrupt the DSP */
2156static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
2157{
2158 struct bus_master_interface *interface = phw->p_interface_buffer;
2159
2160 u32 r;
2161
2162 interface->host_cmd = cmd;
2163 wmb(); /* DSP gets state by DMA, make sure it is written to memory */
2164 /* before we interrupt the DSP */
2165 r = ioread32(phw->prHDCR);
2166 r |= (u32)C6205_HDCR_DSPINT;
2167 iowrite32(r, phw->prHDCR);
2168 r &= ~(u32)C6205_HDCR_DSPINT;
2169 iowrite32(r, phw->prHDCR);
2170}
2171
2172static unsigned int message_count;
2173
2174static u16 message_response_sequence(struct hpi_adapter_obj *pao,
2175 struct hpi_message *phm, struct hpi_response *phr)
2176{
2177#ifndef HPI6205_NO_HSR_POLL
2178 u32 temp2;
2179#endif
2180 u32 time_out, time_out2;
2181 struct hpi_hw_obj *phw = pao->priv;
2182 struct bus_master_interface *interface = phw->p_interface_buffer;
2183 u16 err = 0;
2184
2185 message_count++;
2186 /* Assume buffer of type struct bus_master_interface
2187 is allocated "noncacheable" */
2188
2189 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2190 HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");
2191 return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT);
2192 }
2193 interface->u.message_buffer = *phm;
2194 /* signal we want a response */
2195 send_dsp_command(phw, H620_HIF_GET_RESP);
2196
2197 time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);
2198
2199 if (time_out2 == 0) {
2200 HPI_DEBUG_LOG(ERROR,
2201 "(%u) timed out waiting for " "GET_RESP state [%x]\n",
2202 message_count, interface->dsp_ack);
2203 } else {
2204 HPI_DEBUG_LOG(VERBOSE,
2205 "(%u) transition to GET_RESP after %u\n",
2206 message_count, HPI6205_TIMEOUT - time_out2);
2207 }
2208 /* spin waiting on HIF interrupt flag (end of msg process) */
2209 time_out = HPI6205_TIMEOUT;
2210
2211#ifndef HPI6205_NO_HSR_POLL
2212 temp2 = 0;
2213 while ((temp2 == 0) && --time_out) {
2214 temp2 = ioread32(phw->prHSR);
2215 temp2 &= C6205_HSR_INTSRC;
2216 hpios_delay_micro_seconds(1);
2217 }
2218 if (temp2 == C6205_HSR_INTSRC) {
2219 rmb(); /* ensure we see latest value for dsp_ack */
2220 if ((interface->dsp_ack != H620_HIF_GET_RESP)) {
2221 HPI_DEBUG_LOG(DEBUG,
2222 "(%u)interface->dsp_ack(0x%x) != "
2223 "H620_HIF_GET_RESP, t=%u\n", message_count,
2224 interface->dsp_ack,
2225 HPI6205_TIMEOUT - time_out);
2226 } else {
2227 HPI_DEBUG_LOG(VERBOSE,
2228 "(%u)int with GET_RESP after %u\n",
2229 message_count, HPI6205_TIMEOUT - time_out);
2230 }
2231
2232 } else {
2233 /* can we do anything else in response to the error ? */
2234 HPI_DEBUG_LOG(ERROR,
2235 "interrupt from HIF module BAD (function %x)\n",
2236 phm->function);
2237 }
2238
2239 /* reset the interrupt from the DSP */
2240 iowrite32(C6205_HSR_INTSRC, phw->prHSR);
2241#endif
2242
2243 /* read the result */
2244 if (time_out != 0)
2245 *phr = interface->u.response_buffer;
2246
2247 /* set interface back to idle */
2248 send_dsp_command(phw, H620_HIF_IDLE);
2249
2250 if ((time_out == 0) || (time_out2 == 0)) {
2251 HPI_DEBUG_LOG(DEBUG, "something timed out!\n");
2252 return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_TIMEOUT);
2253 }
2254 /* special case for adapter close - */
2255 /* wait for the DSP to indicate it is idle */
2256 if (phm->function == HPI_ADAPTER_CLOSE) {
2257 if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
2258 HPI_DEBUG_LOG(DEBUG,
2259 "timeout waiting for idle "
2260 "(on adapter_close)\n");
2261 return hpi6205_error(0,
2262 HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT);
2263 }
2264 }
2265 err = hpi_validate_response(phm, phr);
2266 return err;
2267}
2268
2269static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
2270 struct hpi_response *phr)
2271{
2272
2273 u16 err = 0;
2274
2275 hpios_dsplock_lock(pao);
2276
2277 err = message_response_sequence(pao, phm, phr);
2278
2279 /* maybe an error response */
2280 if (err) {
2281 /* something failed in the HPI/DSP interface */
2282 phr->error = err;
2283 pao->dsp_crashed++;
2284
2285 /* just the header of the response is valid */
2286 phr->size = sizeof(struct hpi_response_header);
2287 goto err;
2288 } else
2289 pao->dsp_crashed = 0;
2290
2291 if (phr->error != 0) /* something failed in the DSP */
2292 goto err;
2293
2294 switch (phm->function) {
2295 case HPI_OSTREAM_WRITE:
2296 case HPI_ISTREAM_ANC_WRITE:
2297 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2298 phm->u.d.u.data.data_size, H620_HIF_SEND_DATA);
2299 break;
2300
2301 case HPI_ISTREAM_READ:
2302 case HPI_OSTREAM_ANC_READ:
2303 err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data,
2304 phm->u.d.u.data.data_size, H620_HIF_GET_DATA);
2305 break;
2306
2307 case HPI_CONTROL_SET_STATE:
2308 if (phm->object == HPI_OBJ_CONTROLEX
2309 && phm->u.cx.attribute == HPI_COBRANET_SET_DATA)
2310 err = hpi6205_transfer_data(pao,
2311 phm->u.cx.u.cobranet_bigdata.pb_data,
2312 phm->u.cx.u.cobranet_bigdata.byte_count,
2313 H620_HIF_SEND_DATA);
2314 break;
2315
2316 case HPI_CONTROL_GET_STATE:
2317 if (phm->object == HPI_OBJ_CONTROLEX
2318 && phm->u.cx.attribute == HPI_COBRANET_GET_DATA)
2319 err = hpi6205_transfer_data(pao,
2320 phm->u.cx.u.cobranet_bigdata.pb_data,
2321 phr->u.cx.u.cobranet_data.byte_count,
2322 H620_HIF_GET_DATA);
2323 break;
2324 }
2325 phr->error = err;
2326
2327err:
2328 hpios_dsplock_unlock(pao);
2329
2330 return;
2331}
diff --git a/sound/pci/asihpi/hpi6205.h b/sound/pci/asihpi/hpi6205.h
new file mode 100644
index 00000000000..1adae0857cd
--- /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 00000000000..f1cd6f1a0d4
--- /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 00000000000..565102cae4f
--- /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 00000000000..6229022f56c
--- /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 00000000000..4cd85a401b3
--- /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 00000000000..44dccadcc25
--- /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 00000000000..9b10d9a5c25
--- /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 00000000000..d7c24039822
--- /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 00000000000..eda26b31232
--- /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_TYPE);
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 00000000000..8e1d099ed7e
--- /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 00000000000..864ad020c9b
--- /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 00000000000..2ee90dc3d89
--- /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 00000000000..fd49e7542a8
--- /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 00000000000..7396ac54e99
--- /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 00000000000..847f72f03fe
--- /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 00000000000..de615cfdb95
--- /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 00000000000..a62c3f1e5f0
--- /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 00000000000..bb30868ce1a
--- /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}
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 9edc65059e3..6772070ed49 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1139,40 +1139,28 @@ static void snd_cs4281_proc_read(struct snd_info_entry *entry,
1139 snd_iprintf(buffer, "Spurious end IRQs : %u\n", chip->spurious_dtc_irq); 1139 snd_iprintf(buffer, "Spurious end IRQs : %u\n", chip->spurious_dtc_irq);
1140} 1140}
1141 1141
1142static long snd_cs4281_BA0_read(struct snd_info_entry *entry, 1142static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry,
1143 void *file_private_data, 1143 void *file_private_data,
1144 struct file *file, char __user *buf, 1144 struct file *file, char __user *buf,
1145 unsigned long count, unsigned long pos) 1145 size_t count, loff_t pos)
1146{ 1146{
1147 long size;
1148 struct cs4281 *chip = entry->private_data; 1147 struct cs4281 *chip = entry->private_data;
1149 1148
1150 size = count; 1149 if (copy_to_user_fromio(buf, chip->ba0 + pos, count))
1151 if (pos + size > CS4281_BA0_SIZE) 1150 return -EFAULT;
1152 size = (long)CS4281_BA0_SIZE - pos; 1151 return count;
1153 if (size > 0) {
1154 if (copy_to_user_fromio(buf, chip->ba0 + pos, size))
1155 return -EFAULT;
1156 }
1157 return size;
1158} 1152}
1159 1153
1160static long snd_cs4281_BA1_read(struct snd_info_entry *entry, 1154static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry,
1161 void *file_private_data, 1155 void *file_private_data,
1162 struct file *file, char __user *buf, 1156 struct file *file, char __user *buf,
1163 unsigned long count, unsigned long pos) 1157 size_t count, loff_t pos)
1164{ 1158{
1165 long size;
1166 struct cs4281 *chip = entry->private_data; 1159 struct cs4281 *chip = entry->private_data;
1167 1160
1168 size = count; 1161 if (copy_to_user_fromio(buf, chip->ba1 + pos, count))
1169 if (pos + size > CS4281_BA1_SIZE) 1162 return -EFAULT;
1170 size = (long)CS4281_BA1_SIZE - pos; 1163 return count;
1171 if (size > 0) {
1172 if (copy_to_user_fromio(buf, chip->ba1 + pos, size))
1173 return -EFAULT;
1174 }
1175 return size;
1176} 1164}
1177 1165
1178static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { 1166static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 3f99a5e8528..aad37082cb6 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2657,21 +2657,16 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
2657 * proc interface 2657 * proc interface
2658 */ 2658 */
2659 2659
2660static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data, 2660static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry,
2661 struct file *file, char __user *buf, 2661 void *file_private_data,
2662 unsigned long count, unsigned long pos) 2662 struct file *file, char __user *buf,
2663 size_t count, loff_t pos)
2663{ 2664{
2664 long size;
2665 struct snd_cs46xx_region *region = entry->private_data; 2665 struct snd_cs46xx_region *region = entry->private_data;
2666 2666
2667 size = count; 2667 if (copy_to_user_fromio(buf, region->remap_addr + pos, count))
2668 if (pos + (size_t)size > region->size) 2668 return -EFAULT;
2669 size = region->size - pos; 2669 return count;
2670 if (size > 0) {
2671 if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
2672 return -EFAULT;
2673 }
2674 return size;
2675} 2670}
2676 2671
2677static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { 2672static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index baa7cd508cd..bc38dd4d071 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -341,15 +341,17 @@ static void snd_emu10k1_proc_acode_read(struct snd_info_entry *entry,
341#define TOTAL_SIZE_CODE (0x200*8) 341#define TOTAL_SIZE_CODE (0x200*8)
342#define A_TOTAL_SIZE_CODE (0x400*8) 342#define A_TOTAL_SIZE_CODE (0x400*8)
343 343
344static long snd_emu10k1_fx8010_read(struct snd_info_entry *entry, 344static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
345 void *file_private_data, 345 void *file_private_data,
346 struct file *file, char __user *buf, 346 struct file *file, char __user *buf,
347 unsigned long count, unsigned long pos) 347 size_t count, loff_t pos)
348{ 348{
349 long size;
350 struct snd_emu10k1 *emu = entry->private_data; 349 struct snd_emu10k1 *emu = entry->private_data;
351 unsigned int offset; 350 unsigned int offset;
352 int tram_addr = 0; 351 int tram_addr = 0;
352 unsigned int *tmp;
353 long res;
354 unsigned int idx;
353 355
354 if (!strcmp(entry->name, "fx8010_tram_addr")) { 356 if (!strcmp(entry->name, "fx8010_tram_addr")) {
355 offset = TANKMEMADDRREGBASE; 357 offset = TANKMEMADDRREGBASE;
@@ -361,30 +363,25 @@ static long snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
361 } else { 363 } else {
362 offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; 364 offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE;
363 } 365 }
364 size = count; 366
365 if (pos + size > entry->size) 367 tmp = kmalloc(count + 8, GFP_KERNEL);
366 size = (long)entry->size - pos; 368 if (!tmp)
367 if (size > 0) { 369 return -ENOMEM;
368 unsigned int *tmp; 370 for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) {
369 long res; 371 unsigned int val;
370 unsigned int idx; 372 val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
371 if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL) 373 if (tram_addr && emu->audigy) {
372 return -ENOMEM; 374 val >>= 11;
373 for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++) 375 val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
374 if (tram_addr && emu->audigy) {
375 tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11;
376 tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
377 } else
378 tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
379 if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size))
380 res = -EFAULT;
381 else {
382 res = size;
383 } 376 }
384 kfree(tmp); 377 tmp[idx] = val;
385 return res;
386 } 378 }
387 return 0; 379 if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count))
380 res = -EFAULT;
381 else
382 res = count;
383 kfree(tmp);
384 return res;
388} 385}
389 386
390static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, 387static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index ecaea9fb48e..23a58f0d6cb 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -104,6 +104,7 @@
104#include <linux/gameport.h> 104#include <linux/gameport.h>
105#include <linux/moduleparam.h> 105#include <linux/moduleparam.h>
106#include <linux/mutex.h> 106#include <linux/mutex.h>
107#include <linux/input.h>
107 108
108#include <sound/core.h> 109#include <sound/core.h>
109#include <sound/pcm.h> 110#include <sound/pcm.h>
@@ -517,14 +518,9 @@ struct es1968 {
517 518
518 /* ALSA Stuff */ 519 /* ALSA Stuff */
519 struct snd_ac97 *ac97; 520 struct snd_ac97 *ac97;
520 struct snd_kcontrol *master_switch; /* for h/w volume control */
521 struct snd_kcontrol *master_volume;
522
523 struct snd_rawmidi *rmidi; 521 struct snd_rawmidi *rmidi;
524 522
525 spinlock_t reg_lock; 523 spinlock_t reg_lock;
526 spinlock_t ac97_lock;
527 struct tasklet_struct hwvol_tq;
528 unsigned int in_suspend; 524 unsigned int in_suspend;
529 525
530 /* Maestro Stuff */ 526 /* Maestro Stuff */
@@ -547,6 +543,16 @@ struct es1968 {
547#ifdef SUPPORT_JOYSTICK 543#ifdef SUPPORT_JOYSTICK
548 struct gameport *gameport; 544 struct gameport *gameport;
549#endif 545#endif
546
547#ifdef CONFIG_SND_ES1968_INPUT
548 struct input_dev *input_dev;
549 char phys[64]; /* physical device path */
550#else
551 struct snd_kcontrol *master_switch; /* for h/w volume control */
552 struct snd_kcontrol *master_volume;
553 spinlock_t ac97_lock;
554 struct tasklet_struct hwvol_tq;
555#endif
550}; 556};
551 557
552static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); 558static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
@@ -632,28 +638,38 @@ static int snd_es1968_ac97_wait_poll(struct es1968 *chip)
632static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) 638static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
633{ 639{
634 struct es1968 *chip = ac97->private_data; 640 struct es1968 *chip = ac97->private_data;
641#ifndef CONFIG_SND_ES1968_INPUT
635 unsigned long flags; 642 unsigned long flags;
643#endif
636 644
637 snd_es1968_ac97_wait(chip); 645 snd_es1968_ac97_wait(chip);
638 646
639 /* Write the bus */ 647 /* Write the bus */
648#ifndef CONFIG_SND_ES1968_INPUT
640 spin_lock_irqsave(&chip->ac97_lock, flags); 649 spin_lock_irqsave(&chip->ac97_lock, flags);
650#endif
641 outw(val, chip->io_port + ESM_AC97_DATA); 651 outw(val, chip->io_port + ESM_AC97_DATA);
642 /*msleep(1);*/ 652 /*msleep(1);*/
643 outb(reg, chip->io_port + ESM_AC97_INDEX); 653 outb(reg, chip->io_port + ESM_AC97_INDEX);
644 /*msleep(1);*/ 654 /*msleep(1);*/
655#ifndef CONFIG_SND_ES1968_INPUT
645 spin_unlock_irqrestore(&chip->ac97_lock, flags); 656 spin_unlock_irqrestore(&chip->ac97_lock, flags);
657#endif
646} 658}
647 659
648static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 660static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
649{ 661{
650 u16 data = 0; 662 u16 data = 0;
651 struct es1968 *chip = ac97->private_data; 663 struct es1968 *chip = ac97->private_data;
664#ifndef CONFIG_SND_ES1968_INPUT
652 unsigned long flags; 665 unsigned long flags;
666#endif
653 667
654 snd_es1968_ac97_wait(chip); 668 snd_es1968_ac97_wait(chip);
655 669
670#ifndef CONFIG_SND_ES1968_INPUT
656 spin_lock_irqsave(&chip->ac97_lock, flags); 671 spin_lock_irqsave(&chip->ac97_lock, flags);
672#endif
657 outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); 673 outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
658 /*msleep(1);*/ 674 /*msleep(1);*/
659 675
@@ -661,7 +677,9 @@ static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short
661 data = inw(chip->io_port + ESM_AC97_DATA); 677 data = inw(chip->io_port + ESM_AC97_DATA);
662 /*msleep(1);*/ 678 /*msleep(1);*/
663 } 679 }
680#ifndef CONFIG_SND_ES1968_INPUT
664 spin_unlock_irqrestore(&chip->ac97_lock, flags); 681 spin_unlock_irqrestore(&chip->ac97_lock, flags);
682#endif
665 683
666 return data; 684 return data;
667} 685}
@@ -1874,13 +1892,17 @@ static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es)
1874 } 1892 }
1875} 1893}
1876 1894
1877/* 1895/* The hardware volume works by incrementing / decrementing 2 counters
1878 */ 1896 (without wrap around) in response to volume button presses and then
1897 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
1898 of a byte wide register. The meaning of bits 0 and 4 is unknown. */
1879static void es1968_update_hw_volume(unsigned long private_data) 1899static void es1968_update_hw_volume(unsigned long private_data)
1880{ 1900{
1881 struct es1968 *chip = (struct es1968 *) private_data; 1901 struct es1968 *chip = (struct es1968 *) private_data;
1882 int x, val; 1902 int x, val;
1903#ifndef CONFIG_SND_ES1968_INPUT
1883 unsigned long flags; 1904 unsigned long flags;
1905#endif
1884 1906
1885 /* Figure out which volume control button was pushed, 1907 /* Figure out which volume control button was pushed,
1886 based on differences from the default register 1908 based on differences from the default register
@@ -1895,6 +1917,7 @@ static void es1968_update_hw_volume(unsigned long private_data)
1895 if (chip->in_suspend) 1917 if (chip->in_suspend)
1896 return; 1918 return;
1897 1919
1920#ifndef CONFIG_SND_ES1968_INPUT
1898 if (! chip->master_switch || ! chip->master_volume) 1921 if (! chip->master_switch || ! chip->master_volume)
1899 return; 1922 return;
1900 1923
@@ -1937,6 +1960,35 @@ static void es1968_update_hw_volume(unsigned long private_data)
1937 break; 1960 break;
1938 } 1961 }
1939 spin_unlock_irqrestore(&chip->ac97_lock, flags); 1962 spin_unlock_irqrestore(&chip->ac97_lock, flags);
1963#else
1964 if (!chip->input_dev)
1965 return;
1966
1967 val = 0;
1968 switch (x) {
1969 case 0x88:
1970 /* The counters have not changed, yet we've received a HV
1971 interrupt. According to tests run by various people this
1972 happens when pressing the mute button. */
1973 val = KEY_MUTE;
1974 break;
1975 case 0xaa:
1976 /* counters increased by 1 -> volume up */
1977 val = KEY_VOLUMEUP;
1978 break;
1979 case 0x66:
1980 /* counters decreased by 1 -> volume down */
1981 val = KEY_VOLUMEDOWN;
1982 break;
1983 }
1984
1985 if (val) {
1986 input_report_key(chip->input_dev, val, 1);
1987 input_sync(chip->input_dev);
1988 input_report_key(chip->input_dev, val, 0);
1989 input_sync(chip->input_dev);
1990 }
1991#endif
1940} 1992}
1941 1993
1942/* 1994/*
@@ -1953,7 +2005,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
1953 outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); 2005 outw(inw(chip->io_port + 4) & 1, chip->io_port + 4);
1954 2006
1955 if (event & ESM_HWVOL_IRQ) 2007 if (event & ESM_HWVOL_IRQ)
2008#ifdef CONFIG_SND_ES1968_INPUT
2009 es1968_update_hw_volume((unsigned long)chip);
2010#else
1956 tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */ 2011 tasklet_schedule(&chip->hwvol_tq); /* we'll do this later */
2012#endif
1957 2013
1958 /* else ack 'em all, i imagine */ 2014 /* else ack 'em all, i imagine */
1959 outb(0xFF, chip->io_port + 0x1A); 2015 outb(0xFF, chip->io_port + 0x1A);
@@ -1993,7 +2049,9 @@ snd_es1968_mixer(struct es1968 *chip)
1993{ 2049{
1994 struct snd_ac97_bus *pbus; 2050 struct snd_ac97_bus *pbus;
1995 struct snd_ac97_template ac97; 2051 struct snd_ac97_template ac97;
2052#ifndef CONFIG_SND_ES1968_INPUT
1996 struct snd_ctl_elem_id elem_id; 2053 struct snd_ctl_elem_id elem_id;
2054#endif
1997 int err; 2055 int err;
1998 static struct snd_ac97_bus_ops ops = { 2056 static struct snd_ac97_bus_ops ops = {
1999 .write = snd_es1968_ac97_write, 2057 .write = snd_es1968_ac97_write,
@@ -2009,6 +2067,7 @@ snd_es1968_mixer(struct es1968 *chip)
2009 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) 2067 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0)
2010 return err; 2068 return err;
2011 2069
2070#ifndef CONFIG_SND_ES1968_INPUT
2012 /* attach master switch / volumes for h/w volume control */ 2071 /* attach master switch / volumes for h/w volume control */
2013 memset(&elem_id, 0, sizeof(elem_id)); 2072 memset(&elem_id, 0, sizeof(elem_id));
2014 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2073 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -2018,6 +2077,7 @@ snd_es1968_mixer(struct es1968 *chip)
2018 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2077 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2019 strcpy(elem_id.name, "Master Playback Volume"); 2078 strcpy(elem_id.name, "Master Playback Volume");
2020 chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); 2079 chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
2080#endif
2021 2081
2022 return 0; 2082 return 0;
2023} 2083}
@@ -2341,6 +2401,7 @@ static void snd_es1968_start_irq(struct es1968 *chip)
2341 w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME; 2401 w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME;
2342 if (chip->rmidi) 2402 if (chip->rmidi)
2343 w |= ESM_HIRQ_MPU401; 2403 w |= ESM_HIRQ_MPU401;
2404 outb(w, chip->io_port + 0x1A);
2344 outw(w, chip->io_port + ESM_PORT_HOST_IRQ); 2405 outw(w, chip->io_port + ESM_PORT_HOST_IRQ);
2345} 2406}
2346 2407
@@ -2474,8 +2535,49 @@ static inline int snd_es1968_create_gameport(struct es1968 *chip, int dev) { ret
2474static inline void snd_es1968_free_gameport(struct es1968 *chip) { } 2535static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
2475#endif 2536#endif
2476 2537
2538#ifdef CONFIG_SND_ES1968_INPUT
2539static int __devinit snd_es1968_input_register(struct es1968 *chip)
2540{
2541 struct input_dev *input_dev;
2542 int err;
2543
2544 input_dev = input_allocate_device();
2545 if (!input_dev)
2546 return -ENOMEM;
2547
2548 snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0",
2549 pci_name(chip->pci));
2550
2551 input_dev->name = chip->card->driver;
2552 input_dev->phys = chip->phys;
2553 input_dev->id.bustype = BUS_PCI;
2554 input_dev->id.vendor = chip->pci->vendor;
2555 input_dev->id.product = chip->pci->device;
2556 input_dev->dev.parent = &chip->pci->dev;
2557
2558 __set_bit(EV_KEY, input_dev->evbit);
2559 __set_bit(KEY_MUTE, input_dev->keybit);
2560 __set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
2561 __set_bit(KEY_VOLUMEUP, input_dev->keybit);
2562
2563 err = input_register_device(input_dev);
2564 if (err) {
2565 input_free_device(input_dev);
2566 return err;
2567 }
2568
2569 chip->input_dev = input_dev;
2570 return 0;
2571}
2572#endif /* CONFIG_SND_ES1968_INPUT */
2573
2477static int snd_es1968_free(struct es1968 *chip) 2574static int snd_es1968_free(struct es1968 *chip)
2478{ 2575{
2576#ifdef CONFIG_SND_ES1968_INPUT
2577 if (chip->input_dev)
2578 input_unregister_device(chip->input_dev);
2579#endif
2580
2479 if (chip->io_port) { 2581 if (chip->io_port) {
2480 if (chip->irq >= 0) 2582 if (chip->irq >= 0)
2481 synchronize_irq(chip->irq); 2583 synchronize_irq(chip->irq);
@@ -2486,8 +2588,6 @@ static int snd_es1968_free(struct es1968 *chip)
2486 if (chip->irq >= 0) 2588 if (chip->irq >= 0)
2487 free_irq(chip->irq, chip); 2589 free_irq(chip->irq, chip);
2488 snd_es1968_free_gameport(chip); 2590 snd_es1968_free_gameport(chip);
2489 chip->master_switch = NULL;
2490 chip->master_volume = NULL;
2491 pci_release_regions(chip->pci); 2591 pci_release_regions(chip->pci);
2492 pci_disable_device(chip->pci); 2592 pci_disable_device(chip->pci);
2493 kfree(chip); 2593 kfree(chip);
@@ -2558,9 +2658,11 @@ static int __devinit snd_es1968_create(struct snd_card *card,
2558 spin_lock_init(&chip->substream_lock); 2658 spin_lock_init(&chip->substream_lock);
2559 INIT_LIST_HEAD(&chip->buf_list); 2659 INIT_LIST_HEAD(&chip->buf_list);
2560 INIT_LIST_HEAD(&chip->substream_list); 2660 INIT_LIST_HEAD(&chip->substream_list);
2561 spin_lock_init(&chip->ac97_lock);
2562 mutex_init(&chip->memory_mutex); 2661 mutex_init(&chip->memory_mutex);
2662#ifndef CONFIG_SND_ES1968_INPUT
2663 spin_lock_init(&chip->ac97_lock);
2563 tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip); 2664 tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
2665#endif
2564 chip->card = card; 2666 chip->card = card;
2565 chip->pci = pci; 2667 chip->pci = pci;
2566 chip->irq = -1; 2668 chip->irq = -1;
@@ -2713,6 +2815,13 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
2713 2815
2714 snd_es1968_create_gameport(chip, dev); 2816 snd_es1968_create_gameport(chip, dev);
2715 2817
2818#ifdef CONFIG_SND_ES1968_INPUT
2819 err = snd_es1968_input_register(chip);
2820 if (err)
2821 snd_printk(KERN_WARNING "Input device registration "
2822 "failed with error %i", err);
2823#endif
2824
2716 snd_es1968_start_irq(chip); 2825 snd_es1968_start_irq(chip);
2717 2826
2718 chip->clock = clock[dev]; 2827 chip->clock = clock[dev];
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 567348b05b5..9194c3c1d04 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -145,6 +145,7 @@ config SND_HDA_CODEC_NVHDMI
145 145
146config SND_HDA_CODEC_INTELHDMI 146config SND_HDA_CODEC_INTELHDMI
147 bool "Build INTEL HDMI HD-audio codec support" 147 bool "Build INTEL HDMI HD-audio codec support"
148 select SND_DYNAMIC_MINORS
148 default y 149 default y
149 help 150 help
150 Say Y here to include INTEL HDMI HD-audio codec support in 151 Say Y here to include INTEL HDMI HD-audio codec support in
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0e76ac2b2ac..a3d638c8c1f 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1209,8 +1209,7 @@ static void free_hda_cache(struct hda_cache_rec *cache)
1209} 1209}
1210 1210
1211/* query the hash. allocate an entry if not found. */ 1211/* query the hash. allocate an entry if not found. */
1212static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, 1212static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key)
1213 u32 key)
1214{ 1213{
1215 u16 idx = key % (u16)ARRAY_SIZE(cache->hash); 1214 u16 idx = key % (u16)ARRAY_SIZE(cache->hash);
1216 u16 cur = cache->hash[idx]; 1215 u16 cur = cache->hash[idx];
@@ -1222,17 +1221,27 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1222 return info; 1221 return info;
1223 cur = info->next; 1222 cur = info->next;
1224 } 1223 }
1224 return NULL;
1225}
1225 1226
1226 /* add a new hash entry */ 1227/* query the hash. allocate an entry if not found. */
1227 info = snd_array_new(&cache->buf); 1228static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
1228 if (!info) 1229 u32 key)
1229 return NULL; 1230{
1230 cur = snd_array_index(&cache->buf, info); 1231 struct hda_cache_head *info = get_hash(cache, key);
1231 info->key = key; 1232 if (!info) {
1232 info->val = 0; 1233 u16 idx, cur;
1233 info->next = cache->hash[idx]; 1234 /* add a new hash entry */
1234 cache->hash[idx] = cur; 1235 info = snd_array_new(&cache->buf);
1235 1236 if (!info)
1237 return NULL;
1238 cur = snd_array_index(&cache->buf, info);
1239 info->key = key;
1240 info->val = 0;
1241 idx = key % (u16)ARRAY_SIZE(cache->hash);
1242 info->next = cache->hash[idx];
1243 cache->hash[idx] = cur;
1244 }
1236 return info; 1245 return info;
1237} 1246}
1238 1247
@@ -1461,6 +1470,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
1461 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); 1470 info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
1462 if (!info) 1471 if (!info)
1463 return 0; 1472 return 0;
1473 if (snd_BUG_ON(mask & ~0xff))
1474 mask &= 0xff;
1464 val &= mask; 1475 val &= mask;
1465 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; 1476 val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
1466 if (info->vol[ch] == val) 1477 if (info->vol[ch] == val)
@@ -1486,6 +1497,9 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
1486 int direction, int idx, int mask, int val) 1497 int direction, int idx, int mask, int val)
1487{ 1498{
1488 int ch, ret = 0; 1499 int ch, ret = 0;
1500
1501 if (snd_BUG_ON(mask & ~0xff))
1502 mask &= 0xff;
1489 for (ch = 0; ch < 2; ch++) 1503 for (ch = 0; ch < 2; ch++)
1490 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, 1504 ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
1491 idx, mask, val); 1505 idx, mask, val);
@@ -2717,6 +2731,41 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2717EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); 2731EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
2718 2732
2719/** 2733/**
2734 * snd_hda_codec_update_cache - check cache and write the cmd only when needed
2735 * @codec: the HDA codec
2736 * @nid: NID to send the command
2737 * @direct: direct flag
2738 * @verb: the verb to send
2739 * @parm: the parameter for the verb
2740 *
2741 * This function works like snd_hda_codec_write_cache(), but it doesn't send
2742 * command if the parameter is already identical with the cached value.
2743 * If not, it sends the command and refreshes the cache.
2744 *
2745 * Returns 0 if successful, or a negative error code.
2746 */
2747int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
2748 int direct, unsigned int verb, unsigned int parm)
2749{
2750 struct hda_cache_head *c;
2751 u32 key;
2752
2753 /* parm may contain the verb stuff for get/set amp */
2754 verb = verb | (parm >> 8);
2755 parm &= 0xff;
2756 key = build_cmd_cache_key(nid, verb);
2757 mutex_lock(&codec->bus->cmd_mutex);
2758 c = get_hash(&codec->cmd_cache, key);
2759 if (c && c->val == parm) {
2760 mutex_unlock(&codec->bus->cmd_mutex);
2761 return 0;
2762 }
2763 mutex_unlock(&codec->bus->cmd_mutex);
2764 return snd_hda_codec_write_cache(codec, nid, direct, verb, parm);
2765}
2766EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
2767
2768/**
2720 * snd_hda_codec_resume_cache - Resume the all commands from the cache 2769 * snd_hda_codec_resume_cache - Resume the all commands from the cache
2721 * @codec: HD-audio codec 2770 * @codec: HD-audio codec
2722 * 2771 *
@@ -4218,7 +4267,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4218 break; 4267 break;
4219 case AC_JACK_MIC_IN: { 4268 case AC_JACK_MIC_IN: {
4220 int preferred, alt; 4269 int preferred, alt;
4221 if (loc == AC_JACK_LOC_FRONT) { 4270 if (loc == AC_JACK_LOC_FRONT ||
4271 (loc & 0x30) == AC_JACK_LOC_INTERNAL) {
4222 preferred = AUTO_PIN_FRONT_MIC; 4272 preferred = AUTO_PIN_FRONT_MIC;
4223 alt = AUTO_PIN_MIC; 4273 alt = AUTO_PIN_MIC;
4224 } else { 4274 } else {
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index b75da47571e..49e939e7e5c 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -885,9 +885,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
885 int direct, unsigned int verb, unsigned int parm); 885 int direct, unsigned int verb, unsigned int parm);
886void snd_hda_sequence_write_cache(struct hda_codec *codec, 886void snd_hda_sequence_write_cache(struct hda_codec *codec,
887 const struct hda_verb *seq); 887 const struct hda_verb *seq);
888int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
889 int direct, unsigned int verb, unsigned int parm);
888void snd_hda_codec_resume_cache(struct hda_codec *codec); 890void snd_hda_codec_resume_cache(struct hda_codec *codec);
889#else 891#else
890#define snd_hda_codec_write_cache snd_hda_codec_write 892#define snd_hda_codec_write_cache snd_hda_codec_write
893#define snd_hda_codec_update_cache snd_hda_codec_write
891#define snd_hda_sequence_write_cache snd_hda_sequence_write 894#define snd_hda_sequence_write_cache snd_hda_sequence_write
892#endif 895#endif
893 896
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cec68152dcb..170610e1d7d 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -84,7 +84,7 @@ module_param_array(bdl_pos_adj, int, NULL, 0644);
84MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); 84MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
85module_param_array(probe_mask, int, NULL, 0444); 85module_param_array(probe_mask, int, NULL, 0444);
86MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); 86MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
87module_param_array(probe_only, bool, NULL, 0444); 87module_param_array(probe_only, int, NULL, 0444);
88MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); 88MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
89module_param(single_cmd, bool, 0444); 89module_param(single_cmd, bool, 0444);
90MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " 90MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
@@ -174,7 +174,7 @@ MODULE_DESCRIPTION("Intel HDA driver");
174#define ICH6_GSTS_FSTS (1 << 1) /* flush status */ 174#define ICH6_GSTS_FSTS (1 << 1) /* flush status */
175#define ICH6_REG_INTCTL 0x20 175#define ICH6_REG_INTCTL 0x20
176#define ICH6_REG_INTSTS 0x24 176#define ICH6_REG_INTSTS 0x24
177#define ICH6_REG_WALCLK 0x30 177#define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */
178#define ICH6_REG_SYNC 0x34 178#define ICH6_REG_SYNC 0x34
179#define ICH6_REG_CORBLBASE 0x40 179#define ICH6_REG_CORBLBASE 0x40
180#define ICH6_REG_CORBUBASE 0x44 180#define ICH6_REG_CORBUBASE 0x44
@@ -340,8 +340,8 @@ struct azx_dev {
340 unsigned int period_bytes; /* size of the period in bytes */ 340 unsigned int period_bytes; /* size of the period in bytes */
341 unsigned int frags; /* number for period in the play buffer */ 341 unsigned int frags; /* number for period in the play buffer */
342 unsigned int fifo_size; /* FIFO size */ 342 unsigned int fifo_size; /* FIFO size */
343 unsigned long start_jiffies; /* start + minimum jiffies */ 343 unsigned long start_wallclk; /* start + minimum wallclk */
344 unsigned long min_jiffies; /* minimum jiffies before position is valid */ 344 unsigned long period_wallclk; /* wallclk for period */
345 345
346 void __iomem *sd_addr; /* stream descriptor pointer */ 346 void __iomem *sd_addr; /* stream descriptor pointer */
347 347
@@ -361,7 +361,6 @@ struct azx_dev {
361 unsigned int opened :1; 361 unsigned int opened :1;
362 unsigned int running :1; 362 unsigned int running :1;
363 unsigned int irq_pending :1; 363 unsigned int irq_pending :1;
364 unsigned int start_flag: 1; /* stream full start flag */
365 /* 364 /*
366 * For VIA: 365 * For VIA:
367 * A flag to ensure DMA position is 0 366 * A flag to ensure DMA position is 0
@@ -425,7 +424,7 @@ struct azx {
425 struct snd_dma_buffer posbuf; 424 struct snd_dma_buffer posbuf;
426 425
427 /* flags */ 426 /* flags */
428 int position_fix; 427 int position_fix[2]; /* for both playback/capture streams */
429 int poll_count; 428 int poll_count;
430 unsigned int running :1; 429 unsigned int running :1;
431 unsigned int initialized :1; 430 unsigned int initialized :1;
@@ -858,10 +857,13 @@ static void azx_power_notify(struct hda_bus *bus);
858#endif 857#endif
859 858
860/* reset codec link */ 859/* reset codec link */
861static int azx_reset(struct azx *chip) 860static int azx_reset(struct azx *chip, int full_reset)
862{ 861{
863 int count; 862 int count;
864 863
864 if (!full_reset)
865 goto __skip;
866
865 /* clear STATESTS */ 867 /* clear STATESTS */
866 azx_writeb(chip, STATESTS, STATESTS_INT_MASK); 868 azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
867 869
@@ -887,6 +889,7 @@ static int azx_reset(struct azx *chip)
887 /* Brent Chartrand said to wait >= 540us for codecs to initialize */ 889 /* Brent Chartrand said to wait >= 540us for codecs to initialize */
888 msleep(1); 890 msleep(1);
889 891
892 __skip:
890 /* check to see if controller is ready */ 893 /* check to see if controller is ready */
891 if (!azx_readb(chip, GCTL)) { 894 if (!azx_readb(chip, GCTL)) {
892 snd_printd(SFX "azx_reset: controller not ready!\n"); 895 snd_printd(SFX "azx_reset: controller not ready!\n");
@@ -998,13 +1001,13 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
998/* 1001/*
999 * reset and start the controller registers 1002 * reset and start the controller registers
1000 */ 1003 */
1001static void azx_init_chip(struct azx *chip) 1004static void azx_init_chip(struct azx *chip, int full_reset)
1002{ 1005{
1003 if (chip->initialized) 1006 if (chip->initialized)
1004 return; 1007 return;
1005 1008
1006 /* reset controller */ 1009 /* reset controller */
1007 azx_reset(chip); 1010 azx_reset(chip, full_reset);
1008 1011
1009 /* initialize interrupts */ 1012 /* initialize interrupts */
1010 azx_int_clear(chip); 1013 azx_int_clear(chip);
@@ -1302,8 +1305,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
1302 azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); 1305 azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
1303 1306
1304 /* enable the position buffer */ 1307 /* enable the position buffer */
1305 if (chip->position_fix == POS_FIX_POSBUF || 1308 if (chip->position_fix[0] == POS_FIX_POSBUF ||
1306 chip->position_fix == POS_FIX_AUTO || 1309 chip->position_fix[0] == POS_FIX_AUTO ||
1310 chip->position_fix[1] == POS_FIX_POSBUF ||
1311 chip->position_fix[1] == POS_FIX_AUTO ||
1307 chip->via_dmapos_patch) { 1312 chip->via_dmapos_patch) {
1308 if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) 1313 if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
1309 azx_writel(chip, DPLBASE, 1314 azx_writel(chip, DPLBASE,
@@ -1348,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus)
1348 1353
1349 bus->in_reset = 1; 1354 bus->in_reset = 1;
1350 azx_stop_chip(chip); 1355 azx_stop_chip(chip);
1351 azx_init_chip(chip); 1356 azx_init_chip(chip, 1);
1352#ifdef CONFIG_PM 1357#ifdef CONFIG_PM
1353 if (chip->initialized) { 1358 if (chip->initialized) {
1354 int i; 1359 int i;
@@ -1422,7 +1427,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
1422 * get back to the sanity state. 1427 * get back to the sanity state.
1423 */ 1428 */
1424 azx_stop_chip(chip); 1429 azx_stop_chip(chip);
1425 azx_init_chip(chip); 1430 azx_init_chip(chip, 1);
1426 } 1431 }
1427 } 1432 }
1428 } 1433 }
@@ -1670,8 +1675,9 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
1670 return err; 1675 return err;
1671 } 1676 }
1672 1677
1673 azx_dev->min_jiffies = (runtime->period_size * HZ) / 1678 /* wallclk has 24Mhz clock source */
1674 (runtime->rate * 2); 1679 azx_dev->period_wallclk = (((runtime->period_size * 24000) /
1680 runtime->rate) * 1000);
1675 azx_setup_controller(chip, azx_dev); 1681 azx_setup_controller(chip, azx_dev);
1676 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1682 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1677 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; 1683 azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
@@ -1725,14 +1731,15 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
1725 if (s->pcm->card != substream->pcm->card) 1731 if (s->pcm->card != substream->pcm->card)
1726 continue; 1732 continue;
1727 azx_dev = get_azx_dev(s); 1733 azx_dev = get_azx_dev(s);
1728 if (rstart) { 1734 if (start) {
1729 azx_dev->start_flag = 1; 1735 azx_dev->start_wallclk = azx_readl(chip, WALLCLK);
1730 azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; 1736 if (!rstart)
1731 } 1737 azx_dev->start_wallclk -=
1732 if (start) 1738 azx_dev->period_wallclk;
1733 azx_stream_start(chip, azx_dev); 1739 azx_stream_start(chip, azx_dev);
1734 else 1740 } else {
1735 azx_stream_stop(chip, azx_dev); 1741 azx_stream_stop(chip, azx_dev);
1742 }
1736 azx_dev->running = start; 1743 azx_dev->running = start;
1737 } 1744 }
1738 spin_unlock(&chip->reg_lock); 1745 spin_unlock(&chip->reg_lock);
@@ -1843,13 +1850,16 @@ static unsigned int azx_get_position(struct azx *chip,
1843 1850
1844 if (chip->via_dmapos_patch) 1851 if (chip->via_dmapos_patch)
1845 pos = azx_via_get_position(chip, azx_dev); 1852 pos = azx_via_get_position(chip, azx_dev);
1846 else if (chip->position_fix == POS_FIX_POSBUF || 1853 else {
1847 chip->position_fix == POS_FIX_AUTO) { 1854 int stream = azx_dev->substream->stream;
1848 /* use the position buffer */ 1855 if (chip->position_fix[stream] == POS_FIX_POSBUF ||
1849 pos = le32_to_cpu(*azx_dev->posbuf); 1856 chip->position_fix[stream] == POS_FIX_AUTO) {
1850 } else { 1857 /* use the position buffer */
1851 /* read LPIB */ 1858 pos = le32_to_cpu(*azx_dev->posbuf);
1852 pos = azx_sd_readl(azx_dev, SD_LPIB); 1859 } else {
1860 /* read LPIB */
1861 pos = azx_sd_readl(azx_dev, SD_LPIB);
1862 }
1853 } 1863 }
1854 if (pos >= azx_dev->bufsize) 1864 if (pos >= azx_dev->bufsize)
1855 pos = 0; 1865 pos = 0;
@@ -1876,32 +1886,35 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
1876 */ 1886 */
1877static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) 1887static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
1878{ 1888{
1889 u32 wallclk;
1879 unsigned int pos; 1890 unsigned int pos;
1891 int stream;
1880 1892
1881 if (azx_dev->start_flag && 1893 wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk;
1882 time_before_eq(jiffies, azx_dev->start_jiffies)) 1894 if (wallclk < (azx_dev->period_wallclk * 2) / 3)
1883 return -1; /* bogus (too early) interrupt */ 1895 return -1; /* bogus (too early) interrupt */
1884 azx_dev->start_flag = 0;
1885 1896
1897 stream = azx_dev->substream->stream;
1886 pos = azx_get_position(chip, azx_dev); 1898 pos = azx_get_position(chip, azx_dev);
1887 if (chip->position_fix == POS_FIX_AUTO) { 1899 if (chip->position_fix[stream] == POS_FIX_AUTO) {
1888 if (!pos) { 1900 if (!pos) {
1889 printk(KERN_WARNING 1901 printk(KERN_WARNING
1890 "hda-intel: Invalid position buffer, " 1902 "hda-intel: Invalid position buffer, "
1891 "using LPIB read method instead.\n"); 1903 "using LPIB read method instead.\n");
1892 chip->position_fix = POS_FIX_LPIB; 1904 chip->position_fix[stream] = POS_FIX_LPIB;
1893 pos = azx_get_position(chip, azx_dev); 1905 pos = azx_get_position(chip, azx_dev);
1894 } else 1906 } else
1895 chip->position_fix = POS_FIX_POSBUF; 1907 chip->position_fix[stream] = POS_FIX_POSBUF;
1896 } 1908 }
1897 1909
1898 if (!bdl_pos_adj[chip->dev_index])
1899 return 1; /* no delayed ack */
1900 if (WARN_ONCE(!azx_dev->period_bytes, 1910 if (WARN_ONCE(!azx_dev->period_bytes,
1901 "hda-intel: zero azx_dev->period_bytes")) 1911 "hda-intel: zero azx_dev->period_bytes"))
1902 return 0; /* this shouldn't happen! */ 1912 return -1; /* this shouldn't happen! */
1903 if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) 1913 if (wallclk <= azx_dev->period_wallclk &&
1904 return 0; /* NG - it's below the period boundary */ 1914 pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
1915 /* NG - it's below the first next period boundary */
1916 return bdl_pos_adj[chip->dev_index] ? 0 : -1;
1917 azx_dev->start_wallclk = wallclk;
1905 return 1; /* OK, it's fine */ 1918 return 1; /* OK, it's fine */
1906} 1919}
1907 1920
@@ -1911,7 +1924,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
1911static void azx_irq_pending_work(struct work_struct *work) 1924static void azx_irq_pending_work(struct work_struct *work)
1912{ 1925{
1913 struct azx *chip = container_of(work, struct azx, irq_pending_work); 1926 struct azx *chip = container_of(work, struct azx, irq_pending_work);
1914 int i, pending; 1927 int i, pending, ok;
1915 1928
1916 if (!chip->irq_pending_warned) { 1929 if (!chip->irq_pending_warned) {
1917 printk(KERN_WARNING 1930 printk(KERN_WARNING
@@ -1930,11 +1943,14 @@ static void azx_irq_pending_work(struct work_struct *work)
1930 !azx_dev->substream || 1943 !azx_dev->substream ||
1931 !azx_dev->running) 1944 !azx_dev->running)
1932 continue; 1945 continue;
1933 if (azx_position_ok(chip, azx_dev)) { 1946 ok = azx_position_ok(chip, azx_dev);
1947 if (ok > 0) {
1934 azx_dev->irq_pending = 0; 1948 azx_dev->irq_pending = 0;
1935 spin_unlock(&chip->reg_lock); 1949 spin_unlock(&chip->reg_lock);
1936 snd_pcm_period_elapsed(azx_dev->substream); 1950 snd_pcm_period_elapsed(azx_dev->substream);
1937 spin_lock(&chip->reg_lock); 1951 spin_lock(&chip->reg_lock);
1952 } else if (ok < 0) {
1953 pending = 0; /* too early */
1938 } else 1954 } else
1939 pending++; 1955 pending++;
1940 } 1956 }
@@ -2112,7 +2128,7 @@ static void azx_power_notify(struct hda_bus *bus)
2112 } 2128 }
2113 } 2129 }
2114 if (power_on) 2130 if (power_on)
2115 azx_init_chip(chip); 2131 azx_init_chip(chip, 1);
2116 else if (chip->running && power_save_controller && 2132 else if (chip->running && power_save_controller &&
2117 !bus->power_keep_link_on) 2133 !bus->power_keep_link_on)
2118 azx_stop_chip(chip); 2134 azx_stop_chip(chip);
@@ -2182,7 +2198,7 @@ static int azx_resume(struct pci_dev *pci)
2182 azx_init_pci(chip); 2198 azx_init_pci(chip);
2183 2199
2184 if (snd_hda_codecs_inuse(chip->bus)) 2200 if (snd_hda_codecs_inuse(chip->bus))
2185 azx_init_chip(chip); 2201 azx_init_chip(chip, 1);
2186 2202
2187 snd_hda_resume(chip->bus); 2203 snd_hda_resume(chip->bus);
2188 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 2204 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2431,7 +2447,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
2431 chip->dev_index = dev; 2447 chip->dev_index = dev;
2432 INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); 2448 INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
2433 2449
2434 chip->position_fix = check_position_fix(chip, position_fix[dev]); 2450 chip->position_fix[0] = chip->position_fix[1] =
2451 check_position_fix(chip, position_fix[dev]);
2435 check_probe_mask(chip, dev); 2452 check_probe_mask(chip, dev);
2436 2453
2437 chip->single_cmd = single_cmd; 2454 chip->single_cmd = single_cmd;
@@ -2577,7 +2594,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
2577 2594
2578 /* initialize chip */ 2595 /* initialize chip */
2579 azx_init_pci(chip); 2596 azx_init_pci(chip);
2580 azx_init_chip(chip); 2597 azx_init_chip(chip, (probe_only[dev] & 2) == 0);
2581 2598
2582 /* codec detection */ 2599 /* codec detection */
2583 if (!chip->codec_mask) { 2600 if (!chip->codec_mask) {
@@ -2666,7 +2683,7 @@ static int __devinit azx_probe(struct pci_dev *pci,
2666 goto out_free; 2683 goto out_free;
2667 } 2684 }
2668#endif 2685#endif
2669 if (!probe_only[dev]) { 2686 if ((probe_only[dev] & 1) == 0) {
2670 err = azx_codec_configure(chip); 2687 err = azx_codec_configure(chip);
2671 if (err < 0) 2688 if (err < 0)
2672 goto out_free; 2689 goto out_free;
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index e9fdfc4b1c5..afbe314a5bf 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -71,9 +71,10 @@ struct ad198x_spec {
71 struct hda_input_mux private_imux; 71 struct hda_input_mux private_imux;
72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 72 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
73 73
74 unsigned int jack_present :1; 74 unsigned int jack_present: 1;
75 unsigned int inv_jack_detect:1; /* inverted jack-detection */ 75 unsigned int inv_jack_detect: 1;/* inverted jack-detection */
76 unsigned int inv_eapd:1; /* inverted EAPD implementation */ 76 unsigned int inv_eapd: 1; /* inverted EAPD implementation */
77 unsigned int analog_beep: 1; /* analog beep input present */
77 78
78#ifdef CONFIG_SND_HDA_POWER_SAVE 79#ifdef CONFIG_SND_HDA_POWER_SAVE
79 struct hda_loopback_check loopback; 80 struct hda_loopback_check loopback;
@@ -165,6 +166,12 @@ static struct snd_kcontrol_new ad_beep_mixer[] = {
165 { } /* end */ 166 { } /* end */
166}; 167};
167 168
169static struct snd_kcontrol_new ad_beep2_mixer[] = {
170 HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
171 HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
172 { } /* end */
173};
174
168#define set_beep_amp(spec, nid, idx, dir) \ 175#define set_beep_amp(spec, nid, idx, dir) \
169 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ 176 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
170#else 177#else
@@ -203,7 +210,8 @@ static int ad198x_build_controls(struct hda_codec *codec)
203#ifdef CONFIG_SND_HDA_INPUT_BEEP 210#ifdef CONFIG_SND_HDA_INPUT_BEEP
204 if (spec->beep_amp) { 211 if (spec->beep_amp) {
205 struct snd_kcontrol_new *knew; 212 struct snd_kcontrol_new *knew;
206 for (knew = ad_beep_mixer; knew->name; knew++) { 213 knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
214 for ( ; knew->name; knew++) {
207 struct snd_kcontrol *kctl; 215 struct snd_kcontrol *kctl;
208 kctl = snd_ctl_new1(knew, codec); 216 kctl = snd_ctl_new1(knew, codec);
209 if (!kctl) 217 if (!kctl)
@@ -3481,6 +3489,8 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
3481 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), 3489 HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
3482 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), 3490 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
3483 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), 3491 HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
3492 HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
3493 HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
3484 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), 3494 HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
3485 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), 3495 HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
3486 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), 3496 HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
@@ -3522,6 +3532,8 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = {
3522 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, 3532 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
3523 /* docking mic boost */ 3533 /* docking mic boost */
3524 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3534 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3535 /* Analog PC Beeper - allow firmware/ACPI beeps */
3536 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a},
3525 /* Analog mixer - docking mic; mute as default */ 3537 /* Analog mixer - docking mic; mute as default */
3526 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, 3538 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
3527 /* enable EAPD bit */ 3539 /* enable EAPD bit */
@@ -3654,6 +3666,7 @@ static int patch_ad1984(struct hda_codec *codec)
3654 spec->input_mux = &ad1984_thinkpad_capture_source; 3666 spec->input_mux = &ad1984_thinkpad_capture_source;
3655 spec->mixers[0] = ad1984_thinkpad_mixers; 3667 spec->mixers[0] = ad1984_thinkpad_mixers;
3656 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; 3668 spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;
3669 spec->analog_beep = 1;
3657 break; 3670 break;
3658 case AD1984_DELL_DESKTOP: 3671 case AD1984_DELL_DESKTOP:
3659 spec->multiout.dig_out_nid = 0; 3672 spec->multiout.dig_out_nid = 0;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index feabb44c7ca..e863649d31f 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -115,6 +115,7 @@ struct conexant_spec {
115 unsigned int port_d_mode; 115 unsigned int port_d_mode;
116 unsigned int dell_vostro:1; 116 unsigned int dell_vostro:1;
117 unsigned int ideapad:1; 117 unsigned int ideapad:1;
118 unsigned int thinkpad:1;
118 119
119 unsigned int ext_mic_present; 120 unsigned int ext_mic_present;
120 unsigned int recording; 121 unsigned int recording;
@@ -1784,6 +1785,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
1784 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1785 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1785 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1786 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1786 /* SPDIF route: PCM */ 1787 /* SPDIF route: PCM */
1788 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1787 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1789 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1788 /* EAPD */ 1790 /* EAPD */
1789 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 1791 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
@@ -1840,6 +1842,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
1840 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, 1842 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
1841 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, 1843 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
1842 /* SPDIF route: PCM */ 1844 /* SPDIF route: PCM */
1845 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* needed for W500 Advanced Mini Dock 250410 */
1843 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, 1846 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
1844 /* EAPD */ 1847 /* EAPD */
1845 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 1848 {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
@@ -1911,7 +1914,7 @@ enum {
1911 CXT5051_LAPTOP, /* Laptops w/ EAPD support */ 1914 CXT5051_LAPTOP, /* Laptops w/ EAPD support */
1912 CXT5051_HP, /* no docking */ 1915 CXT5051_HP, /* no docking */
1913 CXT5051_HP_DV6736, /* HP without mic switch */ 1916 CXT5051_HP_DV6736, /* HP without mic switch */
1914 CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ 1917 CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
1915 CXT5051_F700, /* HP Compaq Presario F700 */ 1918 CXT5051_F700, /* HP Compaq Presario F700 */
1916 CXT5051_TOSHIBA, /* Toshiba M300 & co */ 1919 CXT5051_TOSHIBA, /* Toshiba M300 & co */
1917 CXT5051_MODELS 1920 CXT5051_MODELS
@@ -2033,6 +2036,9 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
2033 /* Port D (HP/LO) */ 2036 /* Port D (HP/LO) */
2034 pinctl = ((spec->hp_present & 2) && spec->cur_eapd) 2037 pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
2035 ? spec->port_d_mode : 0; 2038 ? spec->port_d_mode : 0;
2039 /* Mute if Port A is connected on Thinkpad */
2040 if (spec->thinkpad && (spec->hp_present & 1))
2041 pinctl = 0;
2036 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2042 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2037 pinctl); 2043 pinctl);
2038 2044
@@ -2213,6 +2219,50 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec)
2213 } 2219 }
2214} 2220}
2215 2221
2222/* toggle input of built-in digital mic and mic jack appropriately
2223 order is: external mic -> dock mic -> interal mic */
2224static void cxt5066_thinkpad_automic(struct hda_codec *codec)
2225{
2226 unsigned int ext_present, dock_present;
2227
2228 static struct hda_verb ext_mic_present[] = {
2229 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2230 {0x17, AC_VERB_SET_CONNECT_SEL, 1},
2231 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2232 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2233 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2234 {}
2235 };
2236 static struct hda_verb dock_mic_present[] = {
2237 {0x14, AC_VERB_SET_CONNECT_SEL, 0},
2238 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
2239 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2240 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2241 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2242 {}
2243 };
2244 static struct hda_verb ext_mic_absent[] = {
2245 {0x14, AC_VERB_SET_CONNECT_SEL, 2},
2246 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2247 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2248 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2249 {}
2250 };
2251
2252 ext_present = snd_hda_jack_detect(codec, 0x1b);
2253 dock_present = snd_hda_jack_detect(codec, 0x1a);
2254 if (ext_present) {
2255 snd_printdd("CXT5066: external microphone detected\n");
2256 snd_hda_sequence_write(codec, ext_mic_present);
2257 } else if (dock_present) {
2258 snd_printdd("CXT5066: dock microphone detected\n");
2259 snd_hda_sequence_write(codec, dock_mic_present);
2260 } else {
2261 snd_printdd("CXT5066: external microphone absent\n");
2262 snd_hda_sequence_write(codec, ext_mic_absent);
2263 }
2264}
2265
2216/* mute internal speaker if HP is plugged */ 2266/* mute internal speaker if HP is plugged */
2217static void cxt5066_hp_automute(struct hda_codec *codec) 2267static void cxt5066_hp_automute(struct hda_codec *codec)
2218{ 2268{
@@ -2225,7 +2275,8 @@ static void cxt5066_hp_automute(struct hda_codec *codec)
2225 /* Port D */ 2275 /* Port D */
2226 portD = snd_hda_jack_detect(codec, 0x1c); 2276 portD = snd_hda_jack_detect(codec, 0x1c);
2227 2277
2228 spec->hp_present = !!(portA | portD); 2278 spec->hp_present = !!(portA);
2279 spec->hp_present |= portD ? 2 : 0;
2229 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", 2280 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
2230 portA, portD, spec->hp_present); 2281 portA, portD, spec->hp_present);
2231 cxt5066_update_speaker(codec); 2282 cxt5066_update_speaker(codec);
@@ -2276,6 +2327,20 @@ static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res)
2276 } 2327 }
2277} 2328}
2278 2329
2330/* unsolicited event for jack sensing */
2331static void cxt5066_thinkpad_event(struct hda_codec *codec, unsigned int res)
2332{
2333 snd_printdd("CXT5066_thinkpad: unsol event %x (%x)\n", res, res >> 26);
2334 switch (res >> 26) {
2335 case CONEXANT_HP_EVENT:
2336 cxt5066_hp_automute(codec);
2337 break;
2338 case CONEXANT_MIC_EVENT:
2339 cxt5066_thinkpad_automic(codec);
2340 break;
2341 }
2342}
2343
2279static const struct hda_input_mux cxt5066_analog_mic_boost = { 2344static const struct hda_input_mux cxt5066_analog_mic_boost = {
2280 .num_items = 5, 2345 .num_items = 5,
2281 .items = { 2346 .items = {
@@ -2294,7 +2359,7 @@ static void cxt5066_set_mic_boost(struct hda_codec *codec)
2294 AC_VERB_SET_AMP_GAIN_MUTE, 2359 AC_VERB_SET_AMP_GAIN_MUTE,
2295 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | 2360 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
2296 cxt5066_analog_mic_boost.items[spec->mic_boost].index); 2361 cxt5066_analog_mic_boost.items[spec->mic_boost].index);
2297 if (spec->ideapad) { 2362 if (spec->ideapad || spec->thinkpad) {
2298 /* adjust the internal mic as well...it is not through 0x17 */ 2363 /* adjust the internal mic as well...it is not through 0x17 */
2299 snd_hda_codec_write_cache(codec, 0x23, 0, 2364 snd_hda_codec_write_cache(codec, 0x23, 0,
2300 AC_VERB_SET_AMP_GAIN_MUTE, 2365 AC_VERB_SET_AMP_GAIN_MUTE,
@@ -2782,6 +2847,64 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = {
2782 { } /* end */ 2847 { } /* end */
2783}; 2848};
2784 2849
2850static struct hda_verb cxt5066_init_verbs_thinkpad[] = {
2851 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2852 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2853
2854 /* Port G: internal speakers */
2855 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2856 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2857
2858 /* Port A: HP, Amp */
2859 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2860 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2861
2862 /* Port B: Mic Dock */
2863 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2864
2865 /* Port C: Mic */
2866 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2867
2868 /* Port D: HP Dock, Amp */
2869 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2870 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2871
2872 /* DAC1 */
2873 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2874
2875 /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2876 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2877 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2878 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2879 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2880 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2881 {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */
2882
2883 /* Audio input selector */
2884 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
2885 {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */
2886
2887 /* SPDIF route: PCM */
2888 {0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2889 {0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2890
2891 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2892 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2893
2894 /* internal microphone */
2895 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */
2896
2897 /* EAPD */
2898 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2899
2900 /* enable unsolicited events for Port A, B, C and D */
2901 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2902 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2903 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2904 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2905 { } /* end */
2906};
2907
2785static struct hda_verb cxt5066_init_verbs_portd_lo[] = { 2908static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2786 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, 2909 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2787 { } /* end */ 2910 { } /* end */
@@ -2800,6 +2923,8 @@ static int cxt5066_init(struct hda_codec *codec)
2800 cxt5066_vostro_automic(codec); 2923 cxt5066_vostro_automic(codec);
2801 else if (spec->ideapad) 2924 else if (spec->ideapad)
2802 cxt5066_ideapad_automic(codec); 2925 cxt5066_ideapad_automic(codec);
2926 else if (spec->thinkpad)
2927 cxt5066_thinkpad_automic(codec);
2803 } 2928 }
2804 cxt5066_set_mic_boost(codec); 2929 cxt5066_set_mic_boost(codec);
2805 return 0; 2930 return 0;
@@ -2821,20 +2946,22 @@ static int cxt5066_olpc_init(struct hda_codec *codec)
2821} 2946}
2822 2947
2823enum { 2948enum {
2824 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 2949 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2825 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 2950 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2826 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 2951 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2827 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ 2952 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
2828 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ 2953 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */
2954 CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */
2829 CXT5066_MODELS 2955 CXT5066_MODELS
2830}; 2956};
2831 2957
2832static const char *cxt5066_models[CXT5066_MODELS] = { 2958static const char *cxt5066_models[CXT5066_MODELS] = {
2833 [CXT5066_LAPTOP] = "laptop", 2959 [CXT5066_LAPTOP] = "laptop",
2834 [CXT5066_DELL_LAPTOP] = "dell-laptop", 2960 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2835 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 2961 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
2836 [CXT5066_DELL_VOSTO] = "dell-vostro", 2962 [CXT5066_DELL_VOSTO] = "dell-vostro",
2837 [CXT5066_IDEAPAD] = "ideapad", 2963 [CXT5066_IDEAPAD] = "ideapad",
2964 [CXT5066_THINKPAD] = "thinkpad",
2838}; 2965};
2839 2966
2840static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 2967static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
@@ -2849,6 +2976,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2849 SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), 2976 SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
2850 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), 2977 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
2851 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), 2978 SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
2979 SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
2852 {} 2980 {}
2853}; 2981};
2854 2982
@@ -2956,6 +3084,22 @@ static int patch_cxt5066(struct hda_codec *codec)
2956 /* input source automatically selected */ 3084 /* input source automatically selected */
2957 spec->input_mux = NULL; 3085 spec->input_mux = NULL;
2958 break; 3086 break;
3087 case CXT5066_THINKPAD:
3088 codec->patch_ops.init = cxt5066_init;
3089 codec->patch_ops.unsol_event = cxt5066_thinkpad_event;
3090 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
3091 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
3092 spec->init_verbs[0] = cxt5066_init_verbs_thinkpad;
3093 spec->thinkpad = 1;
3094 spec->port_d_mode = PIN_OUT;
3095 spec->mic_boost = 2; /* default 20dB gain */
3096
3097 /* no S/PDIF out */
3098 spec->multiout.dig_out_nid = 0;
3099
3100 /* input source automatically selected */
3101 spec->input_mux = NULL;
3102 break;
2959 } 3103 }
2960 3104
2961 return 0; 3105 return 0;
@@ -2975,6 +3119,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
2975 .patch = patch_cxt5066 }, 3119 .patch = patch_cxt5066 },
2976 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", 3120 { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
2977 .patch = patch_cxt5066 }, 3121 .patch = patch_cxt5066 },
3122 { .id = 0x14f15069, .name = "CX20585",
3123 .patch = patch_cxt5066 },
2978 {} /* terminator */ 3124 {} /* terminator */
2979}; 3125};
2980 3126
@@ -2983,6 +3129,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15047");
2983MODULE_ALIAS("snd-hda-codec-id:14f15051"); 3129MODULE_ALIAS("snd-hda-codec-id:14f15051");
2984MODULE_ALIAS("snd-hda-codec-id:14f15066"); 3130MODULE_ALIAS("snd-hda-codec-id:14f15066");
2985MODULE_ALIAS("snd-hda-codec-id:14f15067"); 3131MODULE_ALIAS("snd-hda-codec-id:14f15067");
3132MODULE_ALIAS("snd-hda-codec-id:14f15069");
2986 3133
2987MODULE_LICENSE("GPL"); 3134MODULE_LICENSE("GPL");
2988MODULE_DESCRIPTION("Conexant HD-audio codec"); 3135MODULE_DESCRIPTION("Conexant HD-audio codec");
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 2c2bafbf025..86067ee7863 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -766,7 +766,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
766 if (spec->num_pins >= MAX_HDMI_PINS) { 766 if (spec->num_pins >= MAX_HDMI_PINS) {
767 snd_printk(KERN_WARNING 767 snd_printk(KERN_WARNING
768 "HDMI: no space for pin %d\n", pin_nid); 768 "HDMI: no space for pin %d\n", pin_nid);
769 return -EINVAL; 769 return -E2BIG;
770 } 770 }
771 771
772 hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); 772 hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
@@ -788,7 +788,7 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
788 if (spec->num_cvts >= MAX_HDMI_CVTS) { 788 if (spec->num_cvts >= MAX_HDMI_CVTS) {
789 snd_printk(KERN_WARNING 789 snd_printk(KERN_WARNING
790 "HDMI: no space for converter %d\n", nid); 790 "HDMI: no space for converter %d\n", nid);
791 return -EINVAL; 791 return -E2BIG;
792 } 792 }
793 793
794 spec->cvt[spec->num_cvts] = nid; 794 spec->cvt[spec->num_cvts] = nid;
@@ -820,15 +820,13 @@ static int hdmi_parse_codec(struct hda_codec *codec)
820 820
821 switch (type) { 821 switch (type) {
822 case AC_WID_AUD_OUT: 822 case AC_WID_AUD_OUT:
823 if (hdmi_add_cvt(codec, nid) < 0) 823 hdmi_add_cvt(codec, nid);
824 return -EINVAL;
825 break; 824 break;
826 case AC_WID_PIN: 825 case AC_WID_PIN:
827 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); 826 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
828 if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) 827 if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
829 continue; 828 continue;
830 if (hdmi_add_pin(codec, nid) < 0) 829 hdmi_add_pin(codec, nid);
831 return -EINVAL;
832 break; 830 break;
833 } 831 }
834 } 832 }
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 88d035104cc..b81d23e42ac 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -40,7 +40,7 @@
40 * 40 *
41 * The HDA correspondence of pipes/ports are converter/pin nodes. 41 * The HDA correspondence of pipes/ports are converter/pin nodes.
42 */ 42 */
43#define MAX_HDMI_CVTS 2 43#define MAX_HDMI_CVTS 3
44#define MAX_HDMI_PINS 3 44#define MAX_HDMI_PINS 3
45 45
46#include "patch_hdmi.c" 46#include "patch_hdmi.c"
@@ -48,6 +48,7 @@
48static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { 48static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
49 "INTEL HDMI 0", 49 "INTEL HDMI 0",
50 "INTEL HDMI 1", 50 "INTEL HDMI 1",
51 "INTEL HDMI 2",
51}; 52};
52 53
53/* 54/*
@@ -185,14 +186,15 @@ static int patch_intel_hdmi(struct hda_codec *codec)
185} 186}
186 187
187static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { 188static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
188 { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi }, 189{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_intel_hdmi },
189 { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi }, 190{ .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_intel_hdmi },
190 { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi }, 191{ .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_intel_hdmi },
191 { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi }, 192{ .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_intel_hdmi },
192 { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi }, 193{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi },
193 { .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi }, 194{ .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi },
194 { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, 195{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi },
195 {} /* terminator */ 196{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi },
197{} /* terminator */
196}; 198};
197 199
198MODULE_ALIAS("snd-hda-codec-id:808629fb"); 200MODULE_ALIAS("snd-hda-codec-id:808629fb");
@@ -200,6 +202,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862801");
200MODULE_ALIAS("snd-hda-codec-id:80862802"); 202MODULE_ALIAS("snd-hda-codec-id:80862802");
201MODULE_ALIAS("snd-hda-codec-id:80862803"); 203MODULE_ALIAS("snd-hda-codec-id:80862803");
202MODULE_ALIAS("snd-hda-codec-id:80862804"); 204MODULE_ALIAS("snd-hda-codec-id:80862804");
205MODULE_ALIAS("snd-hda-codec-id:80862805");
203MODULE_ALIAS("snd-hda-codec-id:80860054"); 206MODULE_ALIAS("snd-hda-codec-id:80860054");
204MODULE_ALIAS("snd-hda-codec-id:10951392"); 207MODULE_ALIAS("snd-hda-codec-id:10951392");
205 208
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 886d8e46bb3..53538b0f999 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -276,6 +276,18 @@ struct alc_mic_route {
276 276
277#define MUX_IDX_UNDEF ((unsigned char)-1) 277#define MUX_IDX_UNDEF ((unsigned char)-1)
278 278
279struct alc_customize_define {
280 unsigned int sku_cfg;
281 unsigned char port_connectivity;
282 unsigned char check_sum;
283 unsigned char customization;
284 unsigned char external_amp;
285 unsigned int enable_pcbeep:1;
286 unsigned int platform_type:1;
287 unsigned int swap:1;
288 unsigned int override:1;
289};
290
279struct alc_spec { 291struct alc_spec {
280 /* codec parameterization */ 292 /* codec parameterization */
281 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ 293 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
@@ -333,6 +345,7 @@ struct alc_spec {
333 345
334 /* dynamic controls, init_verbs and input_mux */ 346 /* dynamic controls, init_verbs and input_mux */
335 struct auto_pin_cfg autocfg; 347 struct auto_pin_cfg autocfg;
348 struct alc_customize_define cdefine;
336 struct snd_array kctls; 349 struct snd_array kctls;
337 struct hda_input_mux private_imux[3]; 350 struct hda_input_mux private_imux[3];
338 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 351 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -1248,6 +1261,62 @@ static void alc_init_auto_mic(struct hda_codec *codec)
1248 spec->unsol_event = alc_sku_unsol_event; 1261 spec->unsol_event = alc_sku_unsol_event;
1249} 1262}
1250 1263
1264static int alc_auto_parse_customize_define(struct hda_codec *codec)
1265{
1266 unsigned int ass, tmp, i;
1267 unsigned nid = 0;
1268 struct alc_spec *spec = codec->spec;
1269
1270 ass = codec->subsystem_id & 0xffff;
1271 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
1272 goto do_sku;
1273
1274 nid = 0x1d;
1275 if (codec->vendor_id == 0x10ec0260)
1276 nid = 0x17;
1277 ass = snd_hda_codec_get_pincfg(codec, nid);
1278
1279 if (!(ass & 1)) {
1280 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
1281 codec->chip_name, ass);
1282 return -1;
1283 }
1284
1285 /* check sum */
1286 tmp = 0;
1287 for (i = 1; i < 16; i++) {
1288 if ((ass >> i) & 1)
1289 tmp++;
1290 }
1291 if (((ass >> 16) & 0xf) != tmp)
1292 return -1;
1293
1294 spec->cdefine.port_connectivity = ass >> 30;
1295 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
1296 spec->cdefine.check_sum = (ass >> 16) & 0xf;
1297 spec->cdefine.customization = ass >> 8;
1298do_sku:
1299 spec->cdefine.sku_cfg = ass;
1300 spec->cdefine.external_amp = (ass & 0x38) >> 3;
1301 spec->cdefine.platform_type = (ass & 0x4) >> 2;
1302 spec->cdefine.swap = (ass & 0x2) >> 1;
1303 spec->cdefine.override = ass & 0x1;
1304
1305 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
1306 nid, spec->cdefine.sku_cfg);
1307 snd_printd("SKU: port_connectivity=0x%x\n",
1308 spec->cdefine.port_connectivity);
1309 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
1310 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
1311 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
1312 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
1313 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
1314 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
1315 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
1316
1317 return 0;
1318}
1319
1251/* check subsystem ID and set up device-specific initialization; 1320/* check subsystem ID and set up device-specific initialization;
1252 * return 1 if initialized, 0 if invalid SSID 1321 * return 1 if initialized, 0 if invalid SSID
1253 */ 1322 */
@@ -3415,6 +3484,10 @@ static int alc_init(struct hda_codec *codec)
3415 if (spec->init_hook) 3484 if (spec->init_hook)
3416 spec->init_hook(codec); 3485 spec->init_hook(codec);
3417 3486
3487#ifdef CONFIG_SND_HDA_POWER_SAVE
3488 if (codec->patch_ops.check_power_status)
3489 codec->patch_ops.check_power_status(codec, 0x01);
3490#endif
3418 return 0; 3491 return 0;
3419} 3492}
3420 3493
@@ -3775,6 +3848,10 @@ static int alc_resume(struct hda_codec *codec)
3775 codec->patch_ops.init(codec); 3848 codec->patch_ops.init(codec);
3776 snd_hda_codec_resume_amp(codec); 3849 snd_hda_codec_resume_amp(codec);
3777 snd_hda_codec_resume_cache(codec); 3850 snd_hda_codec_resume_cache(codec);
3851#ifdef CONFIG_SND_HDA_POWER_SAVE
3852 if (codec->patch_ops.check_power_status)
3853 codec->patch_ops.check_power_status(codec, 0x01);
3854#endif
3778 return 0; 3855 return 0;
3779} 3856}
3780#endif 3857#endif
@@ -3797,6 +3874,17 @@ static struct hda_codec_ops alc_patch_ops = {
3797 .reboot_notify = alc_shutup, 3874 .reboot_notify = alc_shutup,
3798}; 3875};
3799 3876
3877/* replace the codec chip_name with the given string */
3878static int alc_codec_rename(struct hda_codec *codec, const char *name)
3879{
3880 kfree(codec->chip_name);
3881 codec->chip_name = kstrdup(name, GFP_KERNEL);
3882 if (!codec->chip_name) {
3883 alc_free(codec);
3884 return -ENOMEM;
3885 }
3886 return 0;
3887}
3800 3888
3801/* 3889/*
3802 * Test configuration for debugging 3890 * Test configuration for debugging
@@ -10189,21 +10277,20 @@ static int alc882_auto_create_input_ctls(struct hda_codec *codec,
10189 10277
10190static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, 10278static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
10191 hda_nid_t nid, int pin_type, 10279 hda_nid_t nid, int pin_type,
10192 int dac_idx) 10280 hda_nid_t dac)
10193{ 10281{
10194 /* set as output */
10195 struct alc_spec *spec = codec->spec;
10196 int idx; 10282 int idx;
10197 10283
10284 /* set as output */
10198 alc_set_pin_output(codec, nid, pin_type); 10285 alc_set_pin_output(codec, nid, pin_type);
10199 if (dac_idx >= spec->multiout.num_dacs) 10286
10200 return; 10287 if (dac == 0x25)
10201 if (spec->multiout.dac_nids[dac_idx] == 0x25)
10202 idx = 4; 10288 idx = 4;
10289 else if (dac >= 0x02 && dac <= 0x05)
10290 idx = dac - 2;
10203 else 10291 else
10204 idx = spec->multiout.dac_nids[dac_idx] - 2; 10292 return;
10205 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); 10293 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
10206
10207} 10294}
10208 10295
10209static void alc882_auto_init_multi_out(struct hda_codec *codec) 10296static void alc882_auto_init_multi_out(struct hda_codec *codec)
@@ -10216,22 +10303,29 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec)
10216 int pin_type = get_pin_type(spec->autocfg.line_out_type); 10303 int pin_type = get_pin_type(spec->autocfg.line_out_type);
10217 if (nid) 10304 if (nid)
10218 alc882_auto_set_output_and_unmute(codec, nid, pin_type, 10305 alc882_auto_set_output_and_unmute(codec, nid, pin_type,
10219 i); 10306 spec->multiout.dac_nids[i]);
10220 } 10307 }
10221} 10308}
10222 10309
10223static void alc882_auto_init_hp_out(struct hda_codec *codec) 10310static void alc882_auto_init_hp_out(struct hda_codec *codec)
10224{ 10311{
10225 struct alc_spec *spec = codec->spec; 10312 struct alc_spec *spec = codec->spec;
10226 hda_nid_t pin; 10313 hda_nid_t pin, dac;
10227 10314
10228 pin = spec->autocfg.hp_pins[0]; 10315 pin = spec->autocfg.hp_pins[0];
10229 if (pin) /* connect to front */ 10316 if (pin) {
10230 /* use dac 0 */ 10317 dac = spec->multiout.hp_nid;
10231 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 10318 if (!dac)
10319 dac = spec->multiout.dac_nids[0]; /* to front */
10320 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
10321 }
10232 pin = spec->autocfg.speaker_pins[0]; 10322 pin = spec->autocfg.speaker_pins[0];
10233 if (pin) 10323 if (pin) {
10234 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 10324 dac = spec->multiout.extra_out_nid[0];
10325 if (!dac)
10326 dac = spec->multiout.dac_nids[0]; /* to front */
10327 alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
10328 }
10235} 10329}
10236 10330
10237static void alc882_auto_init_analog_input(struct hda_codec *codec) 10331static void alc882_auto_init_analog_input(struct hda_codec *codec)
@@ -10347,15 +10441,15 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
10347 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); 10441 err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
10348 if (err < 0) 10442 if (err < 0)
10349 return err; 10443 return err;
10444 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10445 "Headphone");
10446 if (err < 0)
10447 return err;
10350 err = alc880_auto_create_extra_out(spec, 10448 err = alc880_auto_create_extra_out(spec,
10351 spec->autocfg.speaker_pins[0], 10449 spec->autocfg.speaker_pins[0],
10352 "Speaker"); 10450 "Speaker");
10353 if (err < 0) 10451 if (err < 0)
10354 return err; 10452 return err;
10355 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
10356 "Headphone");
10357 if (err < 0)
10358 return err;
10359 err = alc882_auto_create_input_ctls(codec, &spec->autocfg); 10453 err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
10360 if (err < 0) 10454 if (err < 0)
10361 return err; 10455 return err;
@@ -10425,6 +10519,8 @@ static int patch_alc882(struct hda_codec *codec)
10425 10519
10426 codec->spec = spec; 10520 codec->spec = spec;
10427 10521
10522 alc_auto_parse_customize_define(codec);
10523
10428 switch (codec->vendor_id) { 10524 switch (codec->vendor_id) {
10429 case 0x10ec0882: 10525 case 0x10ec0882:
10430 case 0x10ec0885: 10526 case 0x10ec0885:
@@ -10484,9 +10580,6 @@ static int patch_alc882(struct hda_codec *codec)
10484 spec->stream_digital_playback = &alc882_pcm_digital_playback; 10580 spec->stream_digital_playback = &alc882_pcm_digital_playback;
10485 spec->stream_digital_capture = &alc882_pcm_digital_capture; 10581 spec->stream_digital_capture = &alc882_pcm_digital_capture;
10486 10582
10487 if (codec->vendor_id == 0x10ec0888)
10488 spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
10489
10490 if (!spec->adc_nids && spec->input_mux) { 10583 if (!spec->adc_nids && spec->input_mux) {
10491 int i, j; 10584 int i, j;
10492 spec->num_adc_nids = 0; 10585 spec->num_adc_nids = 0;
@@ -10521,7 +10614,9 @@ static int patch_alc882(struct hda_codec *codec)
10521 } 10614 }
10522 10615
10523 set_capture_mixer(codec); 10616 set_capture_mixer(codec);
10524 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); 10617
10618 if (spec->cdefine.enable_pcbeep)
10619 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
10525 10620
10526 if (board_config == ALC882_AUTO) 10621 if (board_config == ALC882_AUTO)
10527 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0); 10622 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0);
@@ -12308,6 +12403,7 @@ static int patch_alc262(struct hda_codec *codec)
12308 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); 12403 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
12309 } 12404 }
12310#endif 12405#endif
12406 alc_auto_parse_customize_define(codec);
12311 12407
12312 alc_fix_pll_init(codec, 0x20, 0x0a, 10); 12408 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
12313 12409
@@ -12386,7 +12482,7 @@ static int patch_alc262(struct hda_codec *codec)
12386 } 12482 }
12387 if (!spec->cap_mixer && !spec->no_analog) 12483 if (!spec->cap_mixer && !spec->no_analog)
12388 set_capture_mixer(codec); 12484 set_capture_mixer(codec);
12389 if (!spec->no_analog) 12485 if (!spec->no_analog && spec->cdefine.enable_pcbeep)
12390 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); 12486 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
12391 12487
12392 spec->vmaster_nid = 0x0c; 12488 spec->vmaster_nid = 0x0c;
@@ -14005,6 +14101,35 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
14005 /* NID is set in alc_build_pcms */ 14101 /* NID is set in alc_build_pcms */
14006}; 14102};
14007 14103
14104#ifdef CONFIG_SND_HDA_POWER_SAVE
14105static int alc269_mic2_for_mute_led(struct hda_codec *codec)
14106{
14107 switch (codec->subsystem_id) {
14108 case 0x103c1586:
14109 return 1;
14110 }
14111 return 0;
14112}
14113
14114static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
14115{
14116 /* update mute-LED according to the speaker mute state */
14117 if (nid == 0x01 || nid == 0x14) {
14118 int pinval;
14119 if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
14120 HDA_AMP_MUTE)
14121 pinval = 0x24;
14122 else
14123 pinval = 0x20;
14124 /* mic2 vref pin is used for mute LED control */
14125 snd_hda_codec_update_cache(codec, 0x19, 0,
14126 AC_VERB_SET_PIN_WIDGET_CONTROL,
14127 pinval);
14128 }
14129 return alc_check_power_status(codec, nid);
14130}
14131#endif /* CONFIG_SND_HDA_POWER_SAVE */
14132
14008/* 14133/*
14009 * BIOS auto configuration 14134 * BIOS auto configuration
14010 */ 14135 */
@@ -14082,7 +14207,7 @@ enum {
14082 ALC269_FIXUP_SONY_VAIO, 14207 ALC269_FIXUP_SONY_VAIO,
14083}; 14208};
14084 14209
14085const static struct hda_verb alc269_sony_vaio_fixup_verbs[] = { 14210static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = {
14086 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, 14211 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
14087 {} 14212 {}
14088}; 14213};
@@ -14290,17 +14415,17 @@ static int patch_alc269(struct hda_codec *codec)
14290 14415
14291 codec->spec = spec; 14416 codec->spec = spec;
14292 14417
14293 alc_fix_pll_init(codec, 0x20, 0x04, 15); 14418 alc_auto_parse_customize_define(codec);
14294 14419
14295 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ 14420 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
14296 kfree(codec->chip_name); 14421 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
14297 codec->chip_name = kstrdup("ALC259", GFP_KERNEL); 14422 spec->cdefine.platform_type == 1)
14298 if (!codec->chip_name) { 14423 alc_codec_rename(codec, "ALC271X");
14299 alc_free(codec); 14424 else
14300 return -ENOMEM; 14425 alc_codec_rename(codec, "ALC259");
14301 }
14302 is_alc269vb = 1; 14426 is_alc269vb = 1;
14303 } 14427 } else
14428 alc_fix_pll_init(codec, 0x20, 0x04, 15);
14304 14429
14305 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, 14430 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
14306 alc269_models, 14431 alc269_models,
@@ -14365,7 +14490,8 @@ static int patch_alc269(struct hda_codec *codec)
14365 14490
14366 if (!spec->cap_mixer) 14491 if (!spec->cap_mixer)
14367 set_capture_mixer(codec); 14492 set_capture_mixer(codec);
14368 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); 14493 if (spec->cdefine.enable_pcbeep)
14494 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
14369 14495
14370 if (board_config == ALC269_AUTO) 14496 if (board_config == ALC269_AUTO)
14371 alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0); 14497 alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0);
@@ -14378,6 +14504,8 @@ static int patch_alc269(struct hda_codec *codec)
14378#ifdef CONFIG_SND_HDA_POWER_SAVE 14504#ifdef CONFIG_SND_HDA_POWER_SAVE
14379 if (!spec->loopback.amplist) 14505 if (!spec->loopback.amplist)
14380 spec->loopback.amplist = alc269_loopbacks; 14506 spec->loopback.amplist = alc269_loopbacks;
14507 if (alc269_mic2_for_mute_led(codec))
14508 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
14381#endif 14509#endif
14382 14510
14383 return 0; 14511 return 0;
@@ -18525,16 +18653,16 @@ static int patch_alc662(struct hda_codec *codec)
18525 18653
18526 codec->spec = spec; 18654 codec->spec = spec;
18527 18655
18656 alc_auto_parse_customize_define(codec);
18657
18528 alc_fix_pll_init(codec, 0x20, 0x04, 15); 18658 alc_fix_pll_init(codec, 0x20, 0x04, 15);
18529 18659
18530 if (alc_read_coef_idx(codec, 0)==0x8020){ 18660 if (alc_read_coef_idx(codec, 0) == 0x8020)
18531 kfree(codec->chip_name); 18661 alc_codec_rename(codec, "ALC661");
18532 codec->chip_name = kstrdup("ALC661", GFP_KERNEL); 18662 else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) &&
18533 if (!codec->chip_name) { 18663 codec->bus->pci->subsystem_vendor == 0x1025 &&
18534 alc_free(codec); 18664 spec->cdefine.platform_type == 1)
18535 return -ENOMEM; 18665 alc_codec_rename(codec, "ALC272X");
18536 }
18537 }
18538 18666
18539 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, 18667 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
18540 alc662_models, 18668 alc662_models,
@@ -18584,18 +18712,20 @@ static int patch_alc662(struct hda_codec *codec)
18584 if (!spec->cap_mixer) 18712 if (!spec->cap_mixer)
18585 set_capture_mixer(codec); 18713 set_capture_mixer(codec);
18586 18714
18587 switch (codec->vendor_id) { 18715 if (spec->cdefine.enable_pcbeep) {
18588 case 0x10ec0662: 18716 switch (codec->vendor_id) {
18589 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); 18717 case 0x10ec0662:
18590 break; 18718 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
18591 case 0x10ec0272: 18719 break;
18592 case 0x10ec0663: 18720 case 0x10ec0272:
18593 case 0x10ec0665: 18721 case 0x10ec0663:
18594 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); 18722 case 0x10ec0665:
18595 break; 18723 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
18596 case 0x10ec0273: 18724 break;
18597 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); 18725 case 0x10ec0273:
18598 break; 18726 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
18727 break;
18728 }
18599 } 18729 }
18600 spec->vmaster_nid = 0x02; 18730 spec->vmaster_nid = 0x02;
18601 18731
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 9e66f6d306f..2f6252266a0 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1956,11 +1956,10 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1956 return 0; 1956 return 0;
1957} 1957}
1958 1958
1959
1960/* 1959/*
1961 * initialize the chip 1960 * reset the chip
1962 */ 1961 */
1963static int __devinit aureon_init(struct snd_ice1712 *ice) 1962static int aureon_reset(struct snd_ice1712 *ice)
1964{ 1963{
1965 static const unsigned short wm_inits_aureon[] = { 1964 static const unsigned short wm_inits_aureon[] = {
1966 /* These come first to reduce init pop noise */ 1965 /* These come first to reduce init pop noise */
@@ -2047,30 +2046,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2047 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ 2046 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2048 (unsigned short)-1 2047 (unsigned short)-1
2049 }; 2048 };
2050 struct aureon_spec *spec;
2051 unsigned int tmp; 2049 unsigned int tmp;
2052 const unsigned short *p; 2050 const unsigned short *p;
2053 int err, i; 2051 int err;
2054 2052 struct aureon_spec *spec = ice->spec;
2055 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2056 if (!spec)
2057 return -ENOMEM;
2058 ice->spec = spec;
2059
2060 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2061 ice->num_total_dacs = 6;
2062 ice->num_total_adcs = 2;
2063 } else {
2064 /* aureon 7.1 and prodigy 7.1 */
2065 ice->num_total_dacs = 8;
2066 ice->num_total_adcs = 2;
2067 }
2068
2069 /* to remeber the register values of CS8415 */
2070 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2071 if (!ice->akm)
2072 return -ENOMEM;
2073 ice->akm_codecs = 1;
2074 2053
2075 err = aureon_ac97_init(ice); 2054 err = aureon_ac97_init(ice);
2076 if (err != 0) 2055 if (err != 0)
@@ -2118,6 +2097,61 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2118 /* initialize PCA9554 pin directions & set default input */ 2097 /* initialize PCA9554 pin directions & set default input */
2119 aureon_pca9554_write(ice, PCA9554_DIR, 0x00); 2098 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2120 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ 2099 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
2100 return 0;
2101}
2102
2103/*
2104 * suspend/resume
2105 */
2106#ifdef CONFIG_PM
2107static int aureon_resume(struct snd_ice1712 *ice)
2108{
2109 struct aureon_spec *spec = ice->spec;
2110 int err, i;
2111
2112 err = aureon_reset(ice);
2113 if (err != 0)
2114 return err;
2115
2116 /* workaround for poking volume with alsamixer after resume:
2117 * just set stored volume again */
2118 for (i = 0; i < ice->num_total_dacs; i++)
2119 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2120 return 0;
2121}
2122#endif
2123
2124/*
2125 * initialize the chip
2126 */
2127static int __devinit aureon_init(struct snd_ice1712 *ice)
2128{
2129 struct aureon_spec *spec;
2130 int i, err;
2131
2132 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2133 if (!spec)
2134 return -ENOMEM;
2135 ice->spec = spec;
2136
2137 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2138 ice->num_total_dacs = 6;
2139 ice->num_total_adcs = 2;
2140 } else {
2141 /* aureon 7.1 and prodigy 7.1 */
2142 ice->num_total_dacs = 8;
2143 ice->num_total_adcs = 2;
2144 }
2145
2146 /* to remeber the register values of CS8415 */
2147 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2148 if (!ice->akm)
2149 return -ENOMEM;
2150 ice->akm_codecs = 1;
2151
2152 err = aureon_reset(ice);
2153 if (err != 0)
2154 return err;
2121 2155
2122 spec->master[0] = WM_VOL_MUTE; 2156 spec->master[0] = WM_VOL_MUTE;
2123 spec->master[1] = WM_VOL_MUTE; 2157 spec->master[1] = WM_VOL_MUTE;
@@ -2126,6 +2160,11 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2126 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); 2160 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2127 } 2161 }
2128 2162
2163#ifdef CONFIG_PM
2164 ice->pm_resume = aureon_resume;
2165 ice->pm_suspend_enabled = 1;
2166#endif
2167
2129 return 0; 2168 return 0;
2130} 2169}
2131 2170
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index b56e3367678..3c40d726b46 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -41,6 +41,7 @@
41#include <linux/vmalloc.h> 41#include <linux/vmalloc.h>
42#include <linux/moduleparam.h> 42#include <linux/moduleparam.h>
43#include <linux/firmware.h> 43#include <linux/firmware.h>
44#include <linux/input.h>
44#include <sound/core.h> 45#include <sound/core.h>
45#include <sound/info.h> 46#include <sound/info.h>
46#include <sound/control.h> 47#include <sound/control.h>
@@ -844,11 +845,17 @@ struct snd_m3 {
844 struct m3_dma *substreams; 845 struct m3_dma *substreams;
845 846
846 spinlock_t reg_lock; 847 spinlock_t reg_lock;
847 spinlock_t ac97_lock;
848 848
849#ifdef CONFIG_SND_MAESTRO3_INPUT
850 struct input_dev *input_dev;
851 char phys[64]; /* physical device path */
852#else
853 spinlock_t ac97_lock;
849 struct snd_kcontrol *master_switch; 854 struct snd_kcontrol *master_switch;
850 struct snd_kcontrol *master_volume; 855 struct snd_kcontrol *master_volume;
851 struct tasklet_struct hwvol_tq; 856 struct tasklet_struct hwvol_tq;
857#endif
858
852 unsigned int in_suspend; 859 unsigned int in_suspend;
853 860
854#ifdef CONFIG_PM 861#ifdef CONFIG_PM
@@ -1598,18 +1605,32 @@ static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
1598 } 1605 }
1599} 1606}
1600 1607
1608/* The m3's hardware volume works by incrementing / decrementing 2 counters
1609 (without wrap around) in response to volume button presses and then
1610 generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7
1611 of a byte wide register. The meaning of bits 0 and 4 is unknown. */
1601static void snd_m3_update_hw_volume(unsigned long private_data) 1612static void snd_m3_update_hw_volume(unsigned long private_data)
1602{ 1613{
1603 struct snd_m3 *chip = (struct snd_m3 *) private_data; 1614 struct snd_m3 *chip = (struct snd_m3 *) private_data;
1604 int x, val; 1615 int x, val;
1616#ifndef CONFIG_SND_MAESTRO3_INPUT
1605 unsigned long flags; 1617 unsigned long flags;
1618#endif
1606 1619
1607 /* Figure out which volume control button was pushed, 1620 /* Figure out which volume control button was pushed,
1608 based on differences from the default register 1621 based on differences from the default register
1609 values. */ 1622 values. */
1610 x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee; 1623 x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;
1611 1624
1612 /* Reset the volume control registers. */ 1625 /* Reset the volume counters to 4. Tests on the allegro integrated
1626 into a Compaq N600C laptop, have revealed that:
1627 1) Writing any value will result in the 2 counters being reset to
1628 4 so writing 0x88 is not strictly necessary
1629 2) Writing to any of the 4 involved registers will reset all 4
1630 of them (and reading them always returns the same value for all
1631 of them)
1632 It could be that a maestro deviates from this, so leave the code
1633 as is. */
1613 outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE); 1634 outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);
1614 outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE); 1635 outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);
1615 outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); 1636 outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
@@ -1620,6 +1641,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1620 if (chip->in_suspend) 1641 if (chip->in_suspend)
1621 return; 1642 return;
1622 1643
1644#ifndef CONFIG_SND_MAESTRO3_INPUT
1623 if (!chip->master_switch || !chip->master_volume) 1645 if (!chip->master_switch || !chip->master_volume)
1624 return; 1646 return;
1625 1647
@@ -1629,7 +1651,9 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1629 val = chip->ac97->regs[AC97_MASTER_VOL]; 1651 val = chip->ac97->regs[AC97_MASTER_VOL];
1630 switch (x) { 1652 switch (x) {
1631 case 0x88: 1653 case 0x88:
1632 /* mute */ 1654 /* The counters have not changed, yet we've received a HV
1655 interrupt. According to tests run by various people this
1656 happens when pressing the mute button. */
1633 val ^= 0x8000; 1657 val ^= 0x8000;
1634 chip->ac97->regs[AC97_MASTER_VOL] = val; 1658 chip->ac97->regs[AC97_MASTER_VOL] = val;
1635 outw(val, chip->iobase + CODEC_DATA); 1659 outw(val, chip->iobase + CODEC_DATA);
@@ -1638,7 +1662,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1638 &chip->master_switch->id); 1662 &chip->master_switch->id);
1639 break; 1663 break;
1640 case 0xaa: 1664 case 0xaa:
1641 /* volume up */ 1665 /* counters increased by 1 -> volume up */
1642 if ((val & 0x7f) > 0) 1666 if ((val & 0x7f) > 0)
1643 val--; 1667 val--;
1644 if ((val & 0x7f00) > 0) 1668 if ((val & 0x7f00) > 0)
@@ -1650,7 +1674,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1650 &chip->master_volume->id); 1674 &chip->master_volume->id);
1651 break; 1675 break;
1652 case 0x66: 1676 case 0x66:
1653 /* volume down */ 1677 /* counters decreased by 1 -> volume down */
1654 if ((val & 0x7f) < 0x1f) 1678 if ((val & 0x7f) < 0x1f)
1655 val++; 1679 val++;
1656 if ((val & 0x7f00) < 0x1f00) 1680 if ((val & 0x7f00) < 0x1f00)
@@ -1663,6 +1687,35 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
1663 break; 1687 break;
1664 } 1688 }
1665 spin_unlock_irqrestore(&chip->ac97_lock, flags); 1689 spin_unlock_irqrestore(&chip->ac97_lock, flags);
1690#else
1691 if (!chip->input_dev)
1692 return;
1693
1694 val = 0;
1695 switch (x) {
1696 case 0x88:
1697 /* The counters have not changed, yet we've received a HV
1698 interrupt. According to tests run by various people this
1699 happens when pressing the mute button. */
1700 val = KEY_MUTE;
1701 break;
1702 case 0xaa:
1703 /* counters increased by 1 -> volume up */
1704 val = KEY_VOLUMEUP;
1705 break;
1706 case 0x66:
1707 /* counters decreased by 1 -> volume down */
1708 val = KEY_VOLUMEDOWN;
1709 break;
1710 }
1711
1712 if (val) {
1713 input_report_key(chip->input_dev, val, 1);
1714 input_sync(chip->input_dev);
1715 input_report_key(chip->input_dev, val, 0);
1716 input_sync(chip->input_dev);
1717 }
1718#endif
1666} 1719}
1667 1720
1668static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) 1721static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
@@ -1677,7 +1730,11 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
1677 return IRQ_NONE; 1730 return IRQ_NONE;
1678 1731
1679 if (status & HV_INT_PENDING) 1732 if (status & HV_INT_PENDING)
1733#ifdef CONFIG_SND_MAESTRO3_INPUT
1734 snd_m3_update_hw_volume((unsigned long)chip);
1735#else
1680 tasklet_schedule(&chip->hwvol_tq); 1736 tasklet_schedule(&chip->hwvol_tq);
1737#endif
1681 1738
1682 /* 1739 /*
1683 * ack an assp int if its running 1740 * ack an assp int if its running
@@ -1943,18 +2000,24 @@ static unsigned short
1943snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 2000snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
1944{ 2001{
1945 struct snd_m3 *chip = ac97->private_data; 2002 struct snd_m3 *chip = ac97->private_data;
2003#ifndef CONFIG_SND_MAESTRO3_INPUT
1946 unsigned long flags; 2004 unsigned long flags;
2005#endif
1947 unsigned short data = 0xffff; 2006 unsigned short data = 0xffff;
1948 2007
1949 if (snd_m3_ac97_wait(chip)) 2008 if (snd_m3_ac97_wait(chip))
1950 goto fail; 2009 goto fail;
2010#ifndef CONFIG_SND_MAESTRO3_INPUT
1951 spin_lock_irqsave(&chip->ac97_lock, flags); 2011 spin_lock_irqsave(&chip->ac97_lock, flags);
2012#endif
1952 snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); 2013 snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
1953 if (snd_m3_ac97_wait(chip)) 2014 if (snd_m3_ac97_wait(chip))
1954 goto fail_unlock; 2015 goto fail_unlock;
1955 data = snd_m3_inw(chip, CODEC_DATA); 2016 data = snd_m3_inw(chip, CODEC_DATA);
1956fail_unlock: 2017fail_unlock:
2018#ifndef CONFIG_SND_MAESTRO3_INPUT
1957 spin_unlock_irqrestore(&chip->ac97_lock, flags); 2019 spin_unlock_irqrestore(&chip->ac97_lock, flags);
2020#endif
1958fail: 2021fail:
1959 return data; 2022 return data;
1960} 2023}
@@ -1963,14 +2026,20 @@ static void
1963snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) 2026snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
1964{ 2027{
1965 struct snd_m3 *chip = ac97->private_data; 2028 struct snd_m3 *chip = ac97->private_data;
2029#ifndef CONFIG_SND_MAESTRO3_INPUT
1966 unsigned long flags; 2030 unsigned long flags;
2031#endif
1967 2032
1968 if (snd_m3_ac97_wait(chip)) 2033 if (snd_m3_ac97_wait(chip))
1969 return; 2034 return;
2035#ifndef CONFIG_SND_MAESTRO3_INPUT
1970 spin_lock_irqsave(&chip->ac97_lock, flags); 2036 spin_lock_irqsave(&chip->ac97_lock, flags);
2037#endif
1971 snd_m3_outw(chip, val, CODEC_DATA); 2038 snd_m3_outw(chip, val, CODEC_DATA);
1972 snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); 2039 snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
2040#ifndef CONFIG_SND_MAESTRO3_INPUT
1973 spin_unlock_irqrestore(&chip->ac97_lock, flags); 2041 spin_unlock_irqrestore(&chip->ac97_lock, flags);
2042#endif
1974} 2043}
1975 2044
1976 2045
@@ -2077,7 +2146,9 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
2077{ 2146{
2078 struct snd_ac97_bus *pbus; 2147 struct snd_ac97_bus *pbus;
2079 struct snd_ac97_template ac97; 2148 struct snd_ac97_template ac97;
2149#ifndef CONFIG_SND_MAESTRO3_INPUT
2080 struct snd_ctl_elem_id elem_id; 2150 struct snd_ctl_elem_id elem_id;
2151#endif
2081 int err; 2152 int err;
2082 static struct snd_ac97_bus_ops ops = { 2153 static struct snd_ac97_bus_ops ops = {
2083 .write = snd_m3_ac97_write, 2154 .write = snd_m3_ac97_write,
@@ -2097,6 +2168,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
2097 schedule_timeout_uninterruptible(msecs_to_jiffies(100)); 2168 schedule_timeout_uninterruptible(msecs_to_jiffies(100));
2098 snd_ac97_write(chip->ac97, AC97_PCM, 0); 2169 snd_ac97_write(chip->ac97, AC97_PCM, 0);
2099 2170
2171#ifndef CONFIG_SND_MAESTRO3_INPUT
2100 memset(&elem_id, 0, sizeof(elem_id)); 2172 memset(&elem_id, 0, sizeof(elem_id));
2101 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2173 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2102 strcpy(elem_id.name, "Master Playback Switch"); 2174 strcpy(elem_id.name, "Master Playback Switch");
@@ -2105,6 +2177,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
2105 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 2177 elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2106 strcpy(elem_id.name, "Master Playback Volume"); 2178 strcpy(elem_id.name, "Master Playback Volume");
2107 chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); 2179 chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
2180#endif
2108 2181
2109 return 0; 2182 return 0;
2110} 2183}
@@ -2370,6 +2443,7 @@ snd_m3_enable_ints(struct snd_m3 *chip)
2370 val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/; 2443 val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/;
2371 if (chip->hv_config & HV_CTRL_ENABLE) 2444 if (chip->hv_config & HV_CTRL_ENABLE)
2372 val |= HV_INT_ENABLE; 2445 val |= HV_INT_ENABLE;
2446 outb(val, chip->iobase + HOST_INT_STATUS);
2373 outw(val, io + HOST_INT_CTRL); 2447 outw(val, io + HOST_INT_CTRL);
2374 outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, 2448 outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
2375 io + ASSP_CONTROL_C); 2449 io + ASSP_CONTROL_C);
@@ -2384,6 +2458,11 @@ static int snd_m3_free(struct snd_m3 *chip)
2384 struct m3_dma *s; 2458 struct m3_dma *s;
2385 int i; 2459 int i;
2386 2460
2461#ifdef CONFIG_SND_MAESTRO3_INPUT
2462 if (chip->input_dev)
2463 input_unregister_device(chip->input_dev);
2464#endif
2465
2387 if (chip->substreams) { 2466 if (chip->substreams) {
2388 spin_lock_irq(&chip->reg_lock); 2467 spin_lock_irq(&chip->reg_lock);
2389 for (i = 0; i < chip->num_substreams; i++) { 2468 for (i = 0; i < chip->num_substreams; i++) {
@@ -2510,6 +2589,41 @@ static int m3_resume(struct pci_dev *pci)
2510} 2589}
2511#endif /* CONFIG_PM */ 2590#endif /* CONFIG_PM */
2512 2591
2592#ifdef CONFIG_SND_MAESTRO3_INPUT
2593static int __devinit snd_m3_input_register(struct snd_m3 *chip)
2594{
2595 struct input_dev *input_dev;
2596 int err;
2597
2598 input_dev = input_allocate_device();
2599 if (!input_dev)
2600 return -ENOMEM;
2601
2602 snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0",
2603 pci_name(chip->pci));
2604
2605 input_dev->name = chip->card->driver;
2606 input_dev->phys = chip->phys;
2607 input_dev->id.bustype = BUS_PCI;
2608 input_dev->id.vendor = chip->pci->vendor;
2609 input_dev->id.product = chip->pci->device;
2610 input_dev->dev.parent = &chip->pci->dev;
2611
2612 __set_bit(EV_KEY, input_dev->evbit);
2613 __set_bit(KEY_MUTE, input_dev->keybit);
2614 __set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
2615 __set_bit(KEY_VOLUMEUP, input_dev->keybit);
2616
2617 err = input_register_device(input_dev);
2618 if (err) {
2619 input_free_device(input_dev);
2620 return err;
2621 }
2622
2623 chip->input_dev = input_dev;
2624 return 0;
2625}
2626#endif /* CONFIG_INPUT */
2513 2627
2514/* 2628/*
2515 */ 2629 */
@@ -2553,7 +2667,9 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2553 } 2667 }
2554 2668
2555 spin_lock_init(&chip->reg_lock); 2669 spin_lock_init(&chip->reg_lock);
2670#ifndef CONFIG_SND_MAESTRO3_INPUT
2556 spin_lock_init(&chip->ac97_lock); 2671 spin_lock_init(&chip->ac97_lock);
2672#endif
2557 2673
2558 switch (pci->device) { 2674 switch (pci->device) {
2559 case PCI_DEVICE_ID_ESS_ALLEGRO: 2675 case PCI_DEVICE_ID_ESS_ALLEGRO:
@@ -2636,7 +2752,9 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2636 2752
2637 snd_m3_hv_init(chip); 2753 snd_m3_hv_init(chip);
2638 2754
2755#ifndef CONFIG_SND_MAESTRO3_INPUT
2639 tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); 2756 tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
2757#endif
2640 2758
2641 if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, 2759 if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
2642 card->driver, chip)) { 2760 card->driver, chip)) {
@@ -2668,7 +2786,16 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2668 2786
2669 if ((err = snd_m3_pcm(chip, 0)) < 0) 2787 if ((err = snd_m3_pcm(chip, 0)) < 0)
2670 return err; 2788 return err;
2671 2789
2790#ifdef CONFIG_SND_MAESTRO3_INPUT
2791 if (chip->hv_config & HV_CTRL_ENABLE) {
2792 err = snd_m3_input_register(chip);
2793 if (err)
2794 snd_printk(KERN_WARNING "Input device registration "
2795 "failed with error %i", err);
2796 }
2797#endif
2798
2672 snd_m3_enable_ints(chip); 2799 snd_m3_enable_ints(chip);
2673 snd_m3_assp_continue(chip); 2800 snd_m3_assp_continue(chip);
2674 2801
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 3be8f97c8bc..6c3fd4d1c49 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1102,73 +1102,17 @@ static int snd_mixart_free(struct mixart_mgr *mgr)
1102/* 1102/*
1103 * proc interface 1103 * proc interface
1104 */ 1104 */
1105static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry,
1106 void *private_file_data,
1107 struct file *file,
1108 long long offset,
1109 int orig)
1110{
1111 offset = offset & ~3; /* 4 bytes aligned */
1112
1113 switch(orig) {
1114 case SEEK_SET:
1115 file->f_pos = offset;
1116 break;
1117 case SEEK_CUR:
1118 file->f_pos += offset;
1119 break;
1120 case SEEK_END: /* offset is negative */
1121 file->f_pos = MIXART_BA0_SIZE + offset;
1122 break;
1123 default:
1124 return -EINVAL;
1125 }
1126 if(file->f_pos > MIXART_BA0_SIZE)
1127 file->f_pos = MIXART_BA0_SIZE;
1128 return file->f_pos;
1129}
1130
1131static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry,
1132 void *private_file_data,
1133 struct file *file,
1134 long long offset,
1135 int orig)
1136{
1137 offset = offset & ~3; /* 4 bytes aligned */
1138
1139 switch(orig) {
1140 case SEEK_SET:
1141 file->f_pos = offset;
1142 break;
1143 case SEEK_CUR:
1144 file->f_pos += offset;
1145 break;
1146 case SEEK_END: /* offset is negative */
1147 file->f_pos = MIXART_BA1_SIZE + offset;
1148 break;
1149 default:
1150 return -EINVAL;
1151 }
1152 if(file->f_pos > MIXART_BA1_SIZE)
1153 file->f_pos = MIXART_BA1_SIZE;
1154 return file->f_pos;
1155}
1156 1105
1157/* 1106/*
1158 mixart_BA0 proc interface for BAR 0 - read callback 1107 mixart_BA0 proc interface for BAR 0 - read callback
1159 */ 1108 */
1160static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private_data, 1109static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
1161 struct file *file, char __user *buf, 1110 void *file_private_data,
1162 unsigned long count, unsigned long pos) 1111 struct file *file, char __user *buf,
1112 size_t count, loff_t pos)
1163{ 1113{
1164 struct mixart_mgr *mgr = entry->private_data; 1114 struct mixart_mgr *mgr = entry->private_data;
1165 unsigned long maxsize;
1166 1115
1167 if (pos >= MIXART_BA0_SIZE)
1168 return 0;
1169 maxsize = MIXART_BA0_SIZE - pos;
1170 if (count > maxsize)
1171 count = maxsize;
1172 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ 1116 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1173 if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) 1117 if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
1174 return -EFAULT; 1118 return -EFAULT;
@@ -1178,18 +1122,13 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private
1178/* 1122/*
1179 mixart_BA1 proc interface for BAR 1 - read callback 1123 mixart_BA1 proc interface for BAR 1 - read callback
1180 */ 1124 */
1181static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private_data, 1125static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
1182 struct file *file, char __user *buf, 1126 void *file_private_data,
1183 unsigned long count, unsigned long pos) 1127 struct file *file, char __user *buf,
1128 size_t count, loff_t pos)
1184{ 1129{
1185 struct mixart_mgr *mgr = entry->private_data; 1130 struct mixart_mgr *mgr = entry->private_data;
1186 unsigned long maxsize;
1187 1131
1188 if (pos > MIXART_BA1_SIZE)
1189 return 0;
1190 maxsize = MIXART_BA1_SIZE - pos;
1191 if (count > maxsize)
1192 count = maxsize;
1193 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ 1132 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1194 if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) 1133 if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
1195 return -EFAULT; 1134 return -EFAULT;
@@ -1198,12 +1137,10 @@ static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private
1198 1137
1199static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { 1138static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
1200 .read = snd_mixart_BA0_read, 1139 .read = snd_mixart_BA0_read,
1201 .llseek = snd_mixart_BA0_llseek
1202}; 1140};
1203 1141
1204static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { 1142static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
1205 .read = snd_mixart_BA1_read, 1143 .read = snd_mixart_BA1_read,
1206 .llseek = snd_mixart_BA1_llseek
1207}; 1144};
1208 1145
1209 1146