aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers/vx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/drivers/vx
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/drivers/vx')
-rw-r--r--sound/drivers/vx/Makefile8
-rw-r--r--sound/drivers/vx/vx_cmd.c109
-rw-r--r--sound/drivers/vx/vx_cmd.h246
-rw-r--r--sound/drivers/vx/vx_core.c837
-rw-r--r--sound/drivers/vx/vx_hwdep.c249
-rw-r--r--sound/drivers/vx/vx_mixer.c1000
-rw-r--r--sound/drivers/vx/vx_pcm.c1312
-rw-r--r--sound/drivers/vx/vx_uer.c321
8 files changed, 4082 insertions, 0 deletions
diff --git a/sound/drivers/vx/Makefile b/sound/drivers/vx/Makefile
new file mode 100644
index 000000000000..269bd8544a5d
--- /dev/null
+++ b/sound/drivers/vx/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o
7
8obj-$(CONFIG_SND_VX_LIB) += snd-vx-lib.o
diff --git a/sound/drivers/vx/vx_cmd.c b/sound/drivers/vx/vx_cmd.c
new file mode 100644
index 000000000000..7a221349f285
--- /dev/null
+++ b/sound/drivers/vx/vx_cmd.c
@@ -0,0 +1,109 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * DSP commands
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/vx_core.h>
27#include "vx_cmd.h"
28
29/*
30 * Array of DSP commands
31 */
32static struct vx_cmd_info vx_dsp_cmds[] = {
33[CMD_VERSION] = { 0x010000, 2, RMH_SSIZE_FIXED, 1 },
34[CMD_SUPPORTED] = { 0x020000, 1, RMH_SSIZE_FIXED, 2 },
35[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED, 1 },
36[CMD_SEND_IRQA] = { 0x070001, 1, RMH_SSIZE_FIXED, 0 },
37[CMD_IBL] = { 0x080000, 1, RMH_SSIZE_FIXED, 4 },
38[CMD_ASYNC] = { 0x0A0000, 1, RMH_SSIZE_ARG, 0 },
39[CMD_RES_PIPE] = { 0x400000, 1, RMH_SSIZE_FIXED, 0 },
40[CMD_FREE_PIPE] = { 0x410000, 1, RMH_SSIZE_FIXED, 0 },
41[CMD_CONF_PIPE] = { 0x42A101, 2, RMH_SSIZE_FIXED, 0 },
42[CMD_ABORT_CONF_PIPE] = { 0x42A100, 2, RMH_SSIZE_FIXED, 0 },
43[CMD_PARAM_OUTPUT_PIPE] = { 0x43A000, 2, RMH_SSIZE_FIXED, 0 },
44[CMD_STOP_PIPE] = { 0x470004, 1, RMH_SSIZE_FIXED, 0 },
45[CMD_PIPE_STATE] = { 0x480000, 1, RMH_SSIZE_FIXED, 1 },
46[CMD_PIPE_SPL_COUNT] = { 0x49A000, 2, RMH_SSIZE_FIXED, 2 },
47[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED, 1 },
48[CMD_SIZE_HBUFFER] = { 0x4C0000, 1, RMH_SSIZE_FIXED, 1 },
49[CMD_START_STREAM] = { 0x80A000, 2, RMH_SSIZE_FIXED, 0 },
50[CMD_START_ONE_STREAM] = { 0x800000, 1, RMH_SSIZE_FIXED, 0 },
51[CMD_PAUSE_STREAM] = { 0x81A000, 2, RMH_SSIZE_FIXED, 0 },
52[CMD_PAUSE_ONE_STREAM] = { 0x810000, 1, RMH_SSIZE_FIXED, 0 },
53[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x828000, 2, RMH_SSIZE_FIXED, 0 },
54[CMD_STOP_STREAM] = { 0x830000, 1, RMH_SSIZE_FIXED, 0 },
55[CMD_FORMAT_STREAM_OUT] = { 0x868000, 1, RMH_SSIZE_FIXED, 0 },
56[CMD_FORMAT_STREAM_IN] = { 0x878800, 1, RMH_SSIZE_FIXED, 0 },
57[CMD_GET_STREAM_STATE] = { 0x890001, 2, RMH_SSIZE_FIXED, 1 },
58[CMD_DROP_BYTES_AWAY] = { 0x8A8000, 2, RMH_SSIZE_FIXED, 0 },
59[CMD_GET_REMAINING_BYTES] = { 0x8D0800, 1, RMH_SSIZE_FIXED, 2 },
60[CMD_CONNECT_AUDIO] = { 0xC10000, 1, RMH_SSIZE_FIXED, 0 },
61[CMD_AUDIO_LEVEL_ADJUST] = { 0xC2A000, 3, RMH_SSIZE_FIXED, 0 },
62[CMD_AUDIO_VU_PIC_METER] = { 0xC3A003, 2, RMH_SSIZE_FIXED, 1 },
63[CMD_GET_AUDIO_LEVELS] = { 0xC4A000, 2, RMH_SSIZE_FIXED, 0 },
64[CMD_GET_NOTIFY_EVENT] = { 0x4D0000, 1, RMH_SSIZE_ARG, 0 },
65[CMD_INFO_NOTIFIED] = { 0x0B0000, 1, RMH_SSIZE_FIXED, 2 },
66[CMD_ACCESS_IO_FCT] = { 0x098000, 1, RMH_SSIZE_ARG, 0 },
67[CMD_STATUS_R_BUFFERS] = { 0x440000, 1, RMH_SSIZE_ARG, 0 },
68[CMD_UPDATE_R_BUFFERS] = { 0x848000, 4, RMH_SSIZE_FIXED, 0 },
69[CMD_LOAD_EFFECT_CONTEXT] = { 0x0c8000, 3, RMH_SSIZE_FIXED, 1 },
70[CMD_EFFECT_ONE_PIPE] = { 0x458000, 0, RMH_SSIZE_FIXED, 0 },
71[CMD_MODIFY_CLOCK] = { 0x0d0000, 1, RMH_SSIZE_FIXED, 0 },
72[CMD_STREAM1_OUT_SET_N_LEVELS] ={ 0x858000, 3, RMH_SSIZE_FIXED, 0 },
73[CMD_PURGE_STREAM_DCMDS] = { 0x8b8000, 3, RMH_SSIZE_FIXED, 0 },
74[CMD_NOTIFY_PIPE_TIME] = { 0x4e0000, 1, RMH_SSIZE_FIXED, 0 },
75[CMD_LOAD_EFFECT_CONTEXT_PACKET] = { 0x0c8000, 1, RMH_SSIZE_FIXED, 0 },
76[CMD_RELIC_R_BUFFER] = { 0x8e0800, 1, RMH_SSIZE_FIXED, 1 },
77[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 1, RMH_SSIZE_FIXED, 0 },
78[CMD_NOTIFY_STREAM_TIME] = { 0x8f0000, 1, RMH_SSIZE_FIXED, 0 },
79[CMD_STREAM_SAMPLE_COUNT] = { 0x900000, 1, RMH_SSIZE_FIXED, 2 },
80[CMD_CONFIG_TIME_CODE] = { 0x050000, 2, RMH_SSIZE_FIXED, 0 },
81[CMD_GET_TIME_CODE] = { 0x060000, 1, RMH_SSIZE_FIXED, 5 },
82[CMD_MANAGE_SIGNAL] = { 0x0f0000, 1, RMH_SSIZE_FIXED, 0 },
83[CMD_PARAMETER_STREAM_OUT] = { 0x91A000, 3, RMH_SSIZE_FIXED, 0 },
84[CMD_READ_BOARD_FREQ] = { 0x030000, 1, RMH_SSIZE_FIXED, 2 },
85[CMD_GET_STREAM_LEVELS] = { 0x8c0000, 1, RMH_SSIZE_FIXED, 3 },
86[CMD_PURGE_PIPE_DCMDS] = { 0x4f8000, 3, RMH_SSIZE_FIXED, 0 },
87// [CMD_SET_STREAM_OUT_EFFECTS] = { 0x888000, 34, RMH_SSIZE_FIXED, 0 },
88// [CMD_GET_STREAM_OUT_EFFECTS] = { 0x928000, 2, RMH_SSIZE_FIXED, 32 },
89[CMD_CONNECT_MONITORING] = { 0xC00000, 1, RMH_SSIZE_FIXED, 0 },
90[CMD_STREAM2_OUT_SET_N_LEVELS] = { 0x938000, 3, RMH_SSIZE_FIXED, 0 },
91[CMD_CANCEL_R_BUFFERS] = { 0x948000, 4, RMH_SSIZE_FIXED, 0 },
92[CMD_NOTIFY_END_OF_BUFFER] = { 0x950000, 1, RMH_SSIZE_FIXED, 0 },
93[CMD_GET_STREAM_VU_METER] = { 0x95A000, 2, RMH_SSIZE_ARG, 0 },
94};
95
96/**
97 * vx_init_rmh - initialize the RMH instance
98 * @rmh: the rmh pointer to be initialized
99 * @cmd: the rmh command to be set
100 */
101void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd)
102{
103 snd_assert(cmd < CMD_LAST_INDEX, return);
104 rmh->LgCmd = vx_dsp_cmds[cmd].length;
105 rmh->LgStat = vx_dsp_cmds[cmd].st_length;
106 rmh->DspStat = vx_dsp_cmds[cmd].st_type;
107 rmh->Cmd[0] = vx_dsp_cmds[cmd].opcode;
108}
109
diff --git a/sound/drivers/vx/vx_cmd.h b/sound/drivers/vx/vx_cmd.h
new file mode 100644
index 000000000000..a85248ba3cc5
--- /dev/null
+++ b/sound/drivers/vx/vx_cmd.h
@@ -0,0 +1,246 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * Definitions of DSP commands
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef __VX_CMD_H
24#define __VX_CMD_H
25
26enum {
27 CMD_VERSION,
28 CMD_SUPPORTED,
29 CMD_TEST_IT,
30 CMD_SEND_IRQA,
31 CMD_IBL,
32 CMD_ASYNC,
33 CMD_RES_PIPE,
34 CMD_FREE_PIPE,
35 CMD_CONF_PIPE,
36 CMD_ABORT_CONF_PIPE,
37 CMD_PARAM_OUTPUT_PIPE,
38 CMD_STOP_PIPE,
39 CMD_PIPE_STATE,
40 CMD_PIPE_SPL_COUNT,
41 CMD_CAN_START_PIPE,
42 CMD_SIZE_HBUFFER,
43 CMD_START_STREAM,
44 CMD_START_ONE_STREAM,
45 CMD_PAUSE_STREAM,
46 CMD_PAUSE_ONE_STREAM,
47 CMD_STREAM_OUT_LEVEL_ADJUST,
48 CMD_STOP_STREAM,
49 CMD_FORMAT_STREAM_OUT,
50 CMD_FORMAT_STREAM_IN,
51 CMD_GET_STREAM_STATE,
52 CMD_DROP_BYTES_AWAY,
53 CMD_GET_REMAINING_BYTES,
54 CMD_CONNECT_AUDIO,
55 CMD_AUDIO_LEVEL_ADJUST,
56 CMD_AUDIO_VU_PIC_METER,
57 CMD_GET_AUDIO_LEVELS,
58 CMD_GET_NOTIFY_EVENT,
59 CMD_INFO_NOTIFIED,
60 CMD_ACCESS_IO_FCT,
61 CMD_STATUS_R_BUFFERS,
62 CMD_UPDATE_R_BUFFERS,
63 CMD_LOAD_EFFECT_CONTEXT,
64 CMD_EFFECT_ONE_PIPE,
65 CMD_MODIFY_CLOCK,
66 CMD_STREAM1_OUT_SET_N_LEVELS,
67 CMD_PURGE_STREAM_DCMDS,
68 CMD_NOTIFY_PIPE_TIME,
69 CMD_LOAD_EFFECT_CONTEXT_PACKET,
70 CMD_RELIC_R_BUFFER,
71 CMD_RESYNC_AUDIO_INPUTS,
72 CMD_NOTIFY_STREAM_TIME,
73 CMD_STREAM_SAMPLE_COUNT,
74 CMD_CONFIG_TIME_CODE,
75 CMD_GET_TIME_CODE,
76 CMD_MANAGE_SIGNAL,
77 CMD_PARAMETER_STREAM_OUT,
78 CMD_READ_BOARD_FREQ,
79 CMD_GET_STREAM_LEVELS,
80 CMD_PURGE_PIPE_DCMDS,
81 // CMD_SET_STREAM_OUT_EFFECTS,
82 // CMD_GET_STREAM_OUT_EFFECTS,
83 CMD_CONNECT_MONITORING,
84 CMD_STREAM2_OUT_SET_N_LEVELS,
85 CMD_CANCEL_R_BUFFERS,
86 CMD_NOTIFY_END_OF_BUFFER,
87 CMD_GET_STREAM_VU_METER,
88 CMD_LAST_INDEX
89};
90
91struct vx_cmd_info {
92 unsigned int opcode; /* command word */
93 int length; /* command length (in words) */
94 int st_type; /* status type (RMH_SSIZE_XXX) */
95 int st_length; /* fixed length */
96};
97
98/* Family and code op of some DSP requests. */
99#define CODE_OP_PIPE_TIME 0x004e0000
100#define CODE_OP_START_STREAM 0x00800000
101#define CODE_OP_PAUSE_STREAM 0x00810000
102#define CODE_OP_OUT_STREAM_LEVEL 0x00820000
103#define CODE_OP_UPDATE_R_BUFFERS 0x00840000
104#define CODE_OP_OUT_STREAM1_LEVEL_CURVE 0x00850000
105#define CODE_OP_OUT_STREAM2_LEVEL_CURVE 0x00930000
106#define CODE_OP_OUT_STREAM_FORMAT 0x00860000
107#define CODE_OP_STREAM_TIME 0x008f0000
108#define CODE_OP_OUT_STREAM_EXTRAPARAMETER 0x00910000
109#define CODE_OP_OUT_AUDIO_LEVEL 0x00c20000
110
111#define NOTIFY_LAST_COMMAND 0x00400000
112
113/* Values for a user delay */
114#define DC_DIFFERED_DELAY (1<<BIT_DIFFERED_COMMAND)
115#define DC_NOTIFY_DELAY (1<<BIT_NOTIFIED_COMMAND)
116#define DC_HBUFFER_DELAY (1<<BIT_TIME_RELATIVE_TO_BUFFER)
117#define DC_MULTIPLE_DELAY (1<<BIT_RESERVED)
118#define DC_STREAM_TIME_DELAY (1<<BIT_STREAM_TIME)
119#define DC_CANCELLED_DELAY (1<<BIT_CANCELLED_COMMAND)
120
121/* Values for tiDelayed field in TIME_INFO structure,
122 * and for pbPause field in PLAY_BUFFER_INFO structure
123 */
124#define BIT_DIFFERED_COMMAND 0
125#define BIT_NOTIFIED_COMMAND 1
126#define BIT_TIME_RELATIVE_TO_BUFFER 2
127#define BIT_RESERVED 3
128#define BIT_STREAM_TIME 4
129#define BIT_CANCELLED_COMMAND 5
130
131/* Access to the "Size" field of the response of the CMD_GET_NOTIFY_EVENT request. */
132#define GET_NOTIFY_EVENT_SIZE_FIELD_MASK 0x000000ff
133
134/* DSP commands general masks */
135#define OPCODE_MASK 0x00ff0000
136#define DSP_DIFFERED_COMMAND_MASK 0x0000C000
137
138/* Notifications (NOTIFY_INFO) */
139#define ALL_CMDS_NOTIFIED 0x0000 // reserved
140#define START_STREAM_NOTIFIED 0x0001
141#define PAUSE_STREAM_NOTIFIED 0x0002
142#define OUT_STREAM_LEVEL_NOTIFIED 0x0003
143#define OUT_STREAM_PARAMETER_NOTIFIED 0x0004 // left for backward compatibility
144#define OUT_STREAM_FORMAT_NOTIFIED 0x0004
145#define PIPE_TIME_NOTIFIED 0x0005
146#define OUT_AUDIO_LEVEL_NOTIFIED 0x0006
147#define OUT_STREAM_LEVEL_CURVE_NOTIFIED 0x0007
148#define STREAM_TIME_NOTIFIED 0x0008
149#define OUT_STREAM_EXTRAPARAMETER_NOTIFIED 0x0009
150#define UNKNOWN_COMMAND_NOTIFIED 0xffff
151
152/* Output pipe parameters setting */
153#define MASK_VALID_PIPE_MPEG_PARAM 0x000040
154#define MASK_VALID_PIPE_BACKWARD_PARAM 0x000020
155#define MASK_SET_PIPE_MPEG_PARAM 0x000002
156#define MASK_SET_PIPE_BACKWARD_PARAM 0x000001
157
158#define MASK_DSP_WORD 0x00FFFFFF
159#define MASK_ALL_STREAM 0x00FFFFFF
160#define MASK_DSP_WORD_LEVEL 0x000001FF
161#define MASK_FIRST_FIELD 0x0000001F
162#define FIELD_SIZE 5
163
164#define COMMAND_RECORD_MASK 0x000800
165
166/* PipeManagement definition bits (PIPE_DECL_INFO) */
167#define P_UNDERRUN_SKIP_SOUND_MASK 0x01
168#define P_PREPARE_FOR_MPEG3_MASK 0x02
169#define P_DO_NOT_RESET_ANALOG_LEVELS 0x04
170#define P_ALLOW_UNDER_ALLOCATION_MASK 0x08
171#define P_DATA_MODE_MASK 0x10
172#define P_ASIO_BUFFER_MANAGEMENT_MASK 0x20
173
174#define BIT_SKIP_SOUND 0x08 // bit 3
175#define BIT_DATA_MODE 0x10 // bit 4
176
177/* Bits in the CMD_MODIFY_CLOCK request. */
178#define CMD_MODIFY_CLOCK_FD_BIT 0x00000001
179#define CMD_MODIFY_CLOCK_T_BIT 0x00000002
180#define CMD_MODIFY_CLOCK_S_BIT 0x00000004
181
182/* Access to the results of the CMD_GET_TIME_CODE RMH. */
183#define TIME_CODE_V_MASK 0x00800000
184#define TIME_CODE_N_MASK 0x00400000
185#define TIME_CODE_B_MASK 0x00200000
186#define TIME_CODE_W_MASK 0x00100000
187
188/* Values for the CMD_MANAGE_SIGNAL RMH. */
189#define MANAGE_SIGNAL_TIME_CODE 0x01
190#define MANAGE_SIGNAL_MIDI 0x02
191
192/* Values for the CMD_CONFIG_TIME_CODE RMH. */
193#define CONFIG_TIME_CODE_CANCEL 0x00001000
194
195/* Mask to get only the effective time from the
196 * high word out of the 2 returned by the DSP
197 */
198#define PCX_TIME_HI_MASK 0x000fffff
199
200/* Values for setting a H-Buffer time */
201#define HBUFFER_TIME_HIGH 0x00200000
202#define HBUFFER_TIME_LOW 0x00000000
203
204#define NOTIFY_MASK_TIME_HIGH 0x00400000
205#define MULTIPLE_MASK_TIME_HIGH 0x00100000
206#define STREAM_MASK_TIME_HIGH 0x00800000
207
208
209/*
210 *
211 */
212void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd);
213
214/**
215 * vx_send_pipe_cmd_params - fill first command word for pipe commands
216 * @rmh: the rmh to be modified
217 * @is_capture: 0 = playback, 1 = capture operation
218 * @param1: first pipe-parameter
219 * @param2: second pipe-parameter
220 */
221static inline void vx_set_pipe_cmd_params(struct vx_rmh *rmh, int is_capture,
222 int param1, int param2)
223{
224 if (is_capture)
225 rmh->Cmd[0] |= COMMAND_RECORD_MASK;
226 rmh->Cmd[0] |= (((u32)param1 & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD;
227
228 if (param2)
229 rmh->Cmd[0] |= ((u32)param2 & MASK_FIRST_FIELD) & MASK_DSP_WORD;
230
231}
232
233/**
234 * vx_set_stream_cmd_params - fill first command word for stream commands
235 * @rmh: the rmh to be modified
236 * @is_capture: 0 = playback, 1 = capture operation
237 * @pipe: the pipe index (zero-based)
238 */
239static inline void vx_set_stream_cmd_params(struct vx_rmh *rmh, int is_capture, int pipe)
240{
241 if (is_capture)
242 rmh->Cmd[0] |= COMMAND_RECORD_MASK;
243 rmh->Cmd[0] |= (((u32)pipe & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD;
244}
245
246#endif /* __VX_CMD_H */
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
new file mode 100644
index 000000000000..c6fa5afa3e9a
--- /dev/null
+++ b/sound/drivers/vx/vx_core.c
@@ -0,0 +1,837 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * Hardware core part
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/interrupt.h>
27#include <linux/init.h>
28#include <linux/device.h>
29#include <linux/firmware.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/asoundef.h>
33#include <sound/info.h>
34#include <asm/io.h>
35#include <sound/vx_core.h>
36#include "vx_cmd.h"
37
38MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
39MODULE_DESCRIPTION("Common routines for Digigram VX drivers");
40MODULE_LICENSE("GPL");
41
42
43/*
44 * snd_vx_delay - delay for the specified time
45 * @xmsec: the time to delay in msec
46 */
47void snd_vx_delay(vx_core_t *chip, int xmsec)
48{
49 if (! in_interrupt() && xmsec >= 1000 / HZ)
50 msleep(xmsec);
51 else
52 mdelay(xmsec);
53}
54
55/*
56 * vx_check_reg_bit - wait for the specified bit is set/reset on a register
57 * @reg: register to check
58 * @mask: bit mask
59 * @bit: resultant bit to be checked
60 * @time: time-out of loop in msec
61 *
62 * returns zero if a bit matches, or a negative error code.
63 */
64int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time)
65{
66 unsigned long end_time = jiffies + (time * HZ + 999) / 1000;
67#ifdef CONFIG_SND_DEBUG
68 static char *reg_names[VX_REG_MAX] = {
69 "ICR", "CVR", "ISR", "IVR", "RXH", "RXM", "RXL",
70 "DMA", "CDSP", "RFREQ", "RUER/V2", "DATA", "MEMIRQ",
71 "ACQ", "BIT0", "BIT1", "MIC0", "MIC1", "MIC2",
72 "MIC3", "INTCSR", "CNTRL", "GPIOC",
73 "LOFREQ", "HIFREQ", "CSUER", "RUER"
74 };
75#endif
76 do {
77 if ((snd_vx_inb(chip, reg) & mask) == bit)
78 return 0;
79 //snd_vx_delay(chip, 10);
80 } while (time_after_eq(end_time, jiffies));
81 snd_printd(KERN_DEBUG "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", reg_names[reg], mask, snd_vx_inb(chip, reg));
82 return -EIO;
83}
84
85/*
86 * vx_send_irq_dsp - set command irq bit
87 * @num: the requested IRQ type, IRQ_XXX
88 *
89 * this triggers the specified IRQ request
90 * returns 0 if successful, or a negative error code.
91 *
92 */
93static int vx_send_irq_dsp(vx_core_t *chip, int num)
94{
95 int nirq;
96
97 /* wait for Hc = 0 */
98 if (snd_vx_check_reg_bit(chip, VX_CVR, CVR_HC, 0, 200) < 0)
99 return -EIO;
100
101 nirq = num;
102 if (vx_has_new_dsp(chip))
103 nirq += VXP_IRQ_OFFSET;
104 vx_outb(chip, CVR, (nirq >> 1) | CVR_HC);
105 return 0;
106}
107
108
109/*
110 * vx_reset_chk - reset CHK bit on ISR
111 *
112 * returns 0 if successful, or a negative error code.
113 */
114static int vx_reset_chk(vx_core_t *chip)
115{
116 /* Reset irq CHK */
117 if (vx_send_irq_dsp(chip, IRQ_RESET_CHK) < 0)
118 return -EIO;
119 /* Wait until CHK = 0 */
120 if (vx_check_isr(chip, ISR_CHK, 0, 200) < 0)
121 return -EIO;
122 return 0;
123}
124
125/*
126 * vx_transfer_end - terminate message transfer
127 * @cmd: IRQ message to send (IRQ_MESS_XXX_END)
128 *
129 * returns 0 if successful, or a negative error code.
130 * the error code can be VX-specific, retrieved via vx_get_error().
131 * NB: call with spinlock held!
132 */
133static int vx_transfer_end(vx_core_t *chip, int cmd)
134{
135 int err;
136
137 if ((err = vx_reset_chk(chip)) < 0)
138 return err;
139
140 /* irq MESS_READ/WRITE_END */
141 if ((err = vx_send_irq_dsp(chip, cmd)) < 0)
142 return err;
143
144 /* Wait CHK = 1 */
145 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
146 return err;
147
148 /* If error, Read RX */
149 if ((err = vx_inb(chip, ISR)) & ISR_ERR) {
150 if ((err = vx_wait_for_rx_full(chip)) < 0) {
151 snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n");
152 return err;
153 }
154 err = vx_inb(chip, RXH) << 16;
155 err |= vx_inb(chip, RXM) << 8;
156 err |= vx_inb(chip, RXL);
157 snd_printd(KERN_DEBUG "transfer_end: error = 0x%x\n", err);
158 return -(VX_ERR_MASK | err);
159 }
160 return 0;
161}
162
163/*
164 * vx_read_status - return the status rmh
165 * @rmh: rmh record to store the status
166 *
167 * returns 0 if successful, or a negative error code.
168 * the error code can be VX-specific, retrieved via vx_get_error().
169 * NB: call with spinlock held!
170 */
171static int vx_read_status(vx_core_t *chip, struct vx_rmh *rmh)
172{
173 int i, err, val, size;
174
175 /* no read necessary? */
176 if (rmh->DspStat == RMH_SSIZE_FIXED && rmh->LgStat == 0)
177 return 0;
178
179 /* Wait for RX full (with timeout protection)
180 * The first word of status is in RX
181 */
182 err = vx_wait_for_rx_full(chip);
183 if (err < 0)
184 return err;
185
186 /* Read RX */
187 val = vx_inb(chip, RXH) << 16;
188 val |= vx_inb(chip, RXM) << 8;
189 val |= vx_inb(chip, RXL);
190
191 /* If status given by DSP, let's decode its size */
192 switch (rmh->DspStat) {
193 case RMH_SSIZE_ARG:
194 size = val & 0xff;
195 rmh->Stat[0] = val & 0xffff00;
196 rmh->LgStat = size + 1;
197 break;
198 case RMH_SSIZE_MASK:
199 /* Let's count the arg numbers from a mask */
200 rmh->Stat[0] = val;
201 size = 0;
202 while (val) {
203 if (val & 0x01)
204 size++;
205 val >>= 1;
206 }
207 rmh->LgStat = size + 1;
208 break;
209 default:
210 /* else retrieve the status length given by the driver */
211 size = rmh->LgStat;
212 rmh->Stat[0] = val; /* Val is the status 1st word */
213 size--; /* hence adjust remaining length */
214 break;
215 }
216
217 if (size < 1)
218 return 0;
219 snd_assert(size <= SIZE_MAX_STATUS, return -EINVAL);
220
221 for (i = 1; i <= size; i++) {
222 /* trigger an irq MESS_WRITE_NEXT */
223 err = vx_send_irq_dsp(chip, IRQ_MESS_WRITE_NEXT);
224 if (err < 0)
225 return err;
226 /* Wait for RX full (with timeout protection) */
227 err = vx_wait_for_rx_full(chip);
228 if (err < 0)
229 return err;
230 rmh->Stat[i] = vx_inb(chip, RXH) << 16;
231 rmh->Stat[i] |= vx_inb(chip, RXM) << 8;
232 rmh->Stat[i] |= vx_inb(chip, RXL);
233 }
234
235 return vx_transfer_end(chip, IRQ_MESS_WRITE_END);
236}
237
238
239#define MASK_MORE_THAN_1_WORD_COMMAND 0x00008000
240#define MASK_1_WORD_COMMAND 0x00ff7fff
241
242/*
243 * vx_send_msg_nolock - send a DSP message and read back the status
244 * @rmh: the rmh record to send and receive
245 *
246 * returns 0 if successful, or a negative error code.
247 * the error code can be VX-specific, retrieved via vx_get_error().
248 *
249 * this function doesn't call spinlock at all.
250 */
251int vx_send_msg_nolock(vx_core_t *chip, struct vx_rmh *rmh)
252{
253 int i, err;
254
255 if (chip->chip_status & VX_STAT_IS_STALE)
256 return -EBUSY;
257
258 if ((err = vx_reset_chk(chip)) < 0) {
259 snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n");
260 return err;
261 }
262
263#if 0
264 printk(KERN_DEBUG "rmh: cmd = 0x%06x, length = %d, stype = %d\n",
265 rmh->Cmd[0], rmh->LgCmd, rmh->DspStat);
266 if (rmh->LgCmd > 1) {
267 printk(KERN_DEBUG " ");
268 for (i = 1; i < rmh->LgCmd; i++)
269 printk("0x%06x ", rmh->Cmd[i]);
270 printk("\n");
271 }
272#endif
273 /* Check bit M is set according to length of the command */
274 if (rmh->LgCmd > 1)
275 rmh->Cmd[0] |= MASK_MORE_THAN_1_WORD_COMMAND;
276 else
277 rmh->Cmd[0] &= MASK_1_WORD_COMMAND;
278
279 /* Wait for TX empty */
280 if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
281 snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n");
282 return err;
283 }
284
285 /* Write Cmd[0] */
286 vx_outb(chip, TXH, (rmh->Cmd[0] >> 16) & 0xff);
287 vx_outb(chip, TXM, (rmh->Cmd[0] >> 8) & 0xff);
288 vx_outb(chip, TXL, rmh->Cmd[0] & 0xff);
289
290 /* Trigger irq MESSAGE */
291 if ((err = vx_send_irq_dsp(chip, IRQ_MESSAGE)) < 0) {
292 snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n");
293 return err;
294 }
295
296 /* Wait for CHK = 1 */
297 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
298 return err;
299
300 /* If error, get error value from RX */
301 if (vx_inb(chip, ISR) & ISR_ERR) {
302 if ((err = vx_wait_for_rx_full(chip)) < 0) {
303 snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n");
304 return err;
305 }
306 err = vx_inb(chip, RXH) << 16;
307 err |= vx_inb(chip, RXM) << 8;
308 err |= vx_inb(chip, RXL);
309 snd_printd(KERN_DEBUG "msg got error = 0x%x at cmd[0]\n", err);
310 err = -(VX_ERR_MASK | err);
311 return err;
312 }
313
314 /* Send the other words */
315 if (rmh->LgCmd > 1) {
316 for (i = 1; i < rmh->LgCmd; i++) {
317 /* Wait for TX ready */
318 if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) {
319 snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n");
320 return err;
321 }
322
323 /* Write Cmd[i] */
324 vx_outb(chip, TXH, (rmh->Cmd[i] >> 16) & 0xff);
325 vx_outb(chip, TXM, (rmh->Cmd[i] >> 8) & 0xff);
326 vx_outb(chip, TXL, rmh->Cmd[i] & 0xff);
327
328 /* Trigger irq MESS_READ_NEXT */
329 if ((err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT)) < 0) {
330 snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n");
331 return err;
332 }
333 }
334 /* Wait for TX empty */
335 if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) {
336 snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n");
337 return err;
338 }
339 /* End of transfer */
340 err = vx_transfer_end(chip, IRQ_MESS_READ_END);
341 if (err < 0)
342 return err;
343 }
344
345 return vx_read_status(chip, rmh);
346}
347
348
349/*
350 * vx_send_msg - send a DSP message with spinlock
351 * @rmh: the rmh record to send and receive
352 *
353 * returns 0 if successful, or a negative error code.
354 * see vx_send_msg_nolock().
355 */
356int vx_send_msg(vx_core_t *chip, struct vx_rmh *rmh)
357{
358 unsigned long flags;
359 int err;
360
361 spin_lock_irqsave(&chip->lock, flags);
362 err = vx_send_msg_nolock(chip, rmh);
363 spin_unlock_irqrestore(&chip->lock, flags);
364 return err;
365}
366
367
368/*
369 * vx_send_rih_nolock - send an RIH to xilinx
370 * @cmd: the command to send
371 *
372 * returns 0 if successful, or a negative error code.
373 * the error code can be VX-specific, retrieved via vx_get_error().
374 *
375 * this function doesn't call spinlock at all.
376 *
377 * unlike RMH, no command is sent to DSP.
378 */
379int vx_send_rih_nolock(vx_core_t *chip, int cmd)
380{
381 int err;
382
383 if (chip->chip_status & VX_STAT_IS_STALE)
384 return -EBUSY;
385
386#if 0
387 printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd);
388#endif
389 if ((err = vx_reset_chk(chip)) < 0)
390 return err;
391 /* send the IRQ */
392 if ((err = vx_send_irq_dsp(chip, cmd)) < 0)
393 return err;
394 /* Wait CHK = 1 */
395 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
396 return err;
397 /* If error, read RX */
398 if (vx_inb(chip, ISR) & ISR_ERR) {
399 if ((err = vx_wait_for_rx_full(chip)) < 0)
400 return err;
401 err = vx_inb(chip, RXH) << 16;
402 err |= vx_inb(chip, RXM) << 8;
403 err |= vx_inb(chip, RXL);
404 return -(VX_ERR_MASK | err);
405 }
406 return 0;
407}
408
409
410/*
411 * vx_send_rih - send an RIH with spinlock
412 * @cmd: the command to send
413 *
414 * see vx_send_rih_nolock().
415 */
416int vx_send_rih(vx_core_t *chip, int cmd)
417{
418 unsigned long flags;
419 int err;
420
421 spin_lock_irqsave(&chip->lock, flags);
422 err = vx_send_rih_nolock(chip, cmd);
423 spin_unlock_irqrestore(&chip->lock, flags);
424 return err;
425}
426
427#define END_OF_RESET_WAIT_TIME 500 /* us */
428
429/**
430 * snd_vx_boot_xilinx - boot up the xilinx interface
431 * @boot: the boot record to load
432 */
433int snd_vx_load_boot_image(vx_core_t *chip, const struct firmware *boot)
434{
435 unsigned int i;
436 int no_fillup = vx_has_new_dsp(chip);
437
438 /* check the length of boot image */
439 snd_assert(boot->size > 0, return -EINVAL);
440 snd_assert(boot->size % 3 == 0, return -EINVAL);
441#if 0
442 {
443 /* more strict check */
444 unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2];
445 snd_assert(boot->size == (c + 2) * 3, return -EINVAL);
446 }
447#endif
448
449 /* reset dsp */
450 vx_reset_dsp(chip);
451
452 udelay(END_OF_RESET_WAIT_TIME); /* another wait? */
453
454 /* download boot strap */
455 for (i = 0; i < 0x600; i += 3) {
456 if (i >= boot->size) {
457 if (no_fillup)
458 break;
459 if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) {
460 snd_printk(KERN_ERR "dsp boot failed at %d\n", i);
461 return -EIO;
462 }
463 vx_outb(chip, TXH, 0);
464 vx_outb(chip, TXM, 0);
465 vx_outb(chip, TXL, 0);
466 } else {
467 unsigned char *image = boot->data + i;
468 if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) {
469 snd_printk(KERN_ERR "dsp boot failed at %d\n", i);
470 return -EIO;
471 }
472 vx_outb(chip, TXH, image[0]);
473 vx_outb(chip, TXM, image[1]);
474 vx_outb(chip, TXL, image[2]);
475 }
476 }
477 return 0;
478}
479
480/*
481 * vx_test_irq_src - query the source of interrupts
482 *
483 * called from irq handler only
484 */
485static int vx_test_irq_src(vx_core_t *chip, unsigned int *ret)
486{
487 int err;
488
489 vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT);
490 spin_lock(&chip->lock);
491 err = vx_send_msg_nolock(chip, &chip->irq_rmh);
492 if (err < 0)
493 *ret = 0;
494 else
495 *ret = chip->irq_rmh.Stat[0];
496 spin_unlock(&chip->lock);
497 return err;
498}
499
500
501/*
502 * vx_interrupt - soft irq handler
503 */
504static void vx_interrupt(unsigned long private_data)
505{
506 vx_core_t *chip = (vx_core_t *) private_data;
507 unsigned int events;
508
509 if (chip->chip_status & VX_STAT_IS_STALE)
510 return;
511
512 if (vx_test_irq_src(chip, &events) < 0)
513 return;
514
515#if 0
516 if (events & 0x000800)
517 printk(KERN_ERR "DSP Stream underrun ! IRQ events = 0x%x\n", events);
518#endif
519 // printk(KERN_DEBUG "IRQ events = 0x%x\n", events);
520
521 /* We must prevent any application using this DSP
522 * and block any further request until the application
523 * either unregisters or reloads the DSP
524 */
525 if (events & FATAL_DSP_ERROR) {
526 snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n");
527 return;
528 }
529
530 /* The start on time code conditions are filled (ie the time code
531 * received by the board is equal to one of those given to it).
532 */
533 if (events & TIME_CODE_EVENT_PENDING)
534 ; /* so far, nothing to do yet */
535
536 /* The frequency has changed on the board (UER mode). */
537 if (events & FREQUENCY_CHANGE_EVENT_PENDING)
538 vx_change_frequency(chip);
539
540 /* update the pcm streams */
541 vx_pcm_update_intr(chip, events);
542}
543
544
545/**
546 * snd_vx_irq_handler - interrupt handler
547 */
548irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
549{
550 vx_core_t *chip = dev;
551
552 if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||
553 (chip->chip_status & VX_STAT_IS_STALE))
554 return IRQ_NONE;
555 if (! vx_test_and_ack(chip))
556 tasklet_hi_schedule(&chip->tq);
557 return IRQ_HANDLED;
558}
559
560
561/*
562 */
563static void vx_reset_board(vx_core_t *chip, int cold_reset)
564{
565 snd_assert(chip->ops->reset_board, return);
566
567 /* current source, later sync'ed with target */
568 chip->audio_source = VX_AUDIO_SRC_LINE;
569 if (cold_reset) {
570 chip->audio_source_target = chip->audio_source;
571 chip->clock_source = INTERNAL_QUARTZ;
572 chip->clock_mode = VX_CLOCK_MODE_AUTO;
573 chip->freq = 48000;
574 chip->uer_detected = VX_UER_MODE_NOT_PRESENT;
575 chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
576 }
577
578 chip->ops->reset_board(chip, cold_reset);
579
580 vx_reset_codec(chip, cold_reset);
581
582 vx_set_internal_clock(chip, chip->freq);
583
584 /* Reset the DSP */
585 vx_reset_dsp(chip);
586
587 if (vx_is_pcmcia(chip)) {
588 /* Acknowledge any pending IRQ and reset the MEMIRQ flag. */
589 vx_test_and_ack(chip);
590 vx_validate_irq(chip, 1);
591 }
592
593 /* init CBits */
594 vx_set_iec958_status(chip, chip->uer_bits);
595}
596
597
598/*
599 * proc interface
600 */
601
602static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
603{
604 vx_core_t *chip = entry->private_data;
605 static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
606 static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
607 static char *clock_mode[] = { "Auto", "Internal", "External" };
608 static char *clock_src[] = { "Internal", "External" };
609 static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
610
611 snd_iprintf(buffer, "%s\n", chip->card->longname);
612 snd_iprintf(buffer, "Xilinx Firmware: %s\n",
613 chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No");
614 snd_iprintf(buffer, "Device Initialized: %s\n",
615 chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No");
616 snd_iprintf(buffer, "DSP audio info:");
617 if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME)
618 snd_iprintf(buffer, " realtime");
619 if (chip->audio_info & VX_AUDIO_INFO_OFFLINE)
620 snd_iprintf(buffer, " offline");
621 if (chip->audio_info & VX_AUDIO_INFO_MPEG1)
622 snd_iprintf(buffer, " mpeg1");
623 if (chip->audio_info & VX_AUDIO_INFO_MPEG2)
624 snd_iprintf(buffer, " mpeg2");
625 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_8)
626 snd_iprintf(buffer, " linear8");
627 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_16)
628 snd_iprintf(buffer, " linear16");
629 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_24)
630 snd_iprintf(buffer, " linear24");
631 snd_iprintf(buffer, "\n");
632 snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?
633 audio_src_vxp[chip->audio_source] :
634 audio_src_vx2[chip->audio_source]);
635 snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);
636 snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);
637 snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
638 snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
639 snd_iprintf(buffer, "Detected UER type: %s\n", uer_type[chip->uer_detected]);
640 snd_iprintf(buffer, "Min/Max/Cur IBL: %d/%d/%d (granularity=%d)\n",
641 chip->ibl.min_size, chip->ibl.max_size, chip->ibl.size,
642 chip->ibl.granularity);
643}
644
645static void vx_proc_init(vx_core_t *chip)
646{
647 snd_info_entry_t *entry;
648
649 if (! snd_card_proc_new(chip->card, "vx-status", &entry))
650 snd_info_set_text_ops(entry, chip, 1024, vx_proc_read);
651}
652
653
654/**
655 * snd_vx_dsp_boot - load the DSP boot
656 */
657int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *boot)
658{
659 int err;
660 int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT);
661
662 vx_reset_board(chip, cold_reset);
663 vx_validate_irq(chip, 0);
664
665 if ((err = snd_vx_load_boot_image(chip, boot)) < 0)
666 return err;
667 snd_vx_delay(chip, 10);
668
669 return 0;
670}
671
672/**
673 * snd_vx_dsp_load - load the DSP image
674 */
675int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp)
676{
677 unsigned int i;
678 int err;
679 unsigned int csum = 0;
680 unsigned char *image, *cptr;
681
682 snd_assert(dsp->size % 3 == 0, return -EINVAL);
683
684 vx_toggle_dac_mute(chip, 1);
685
686 /* Transfert data buffer from PC to DSP */
687 for (i = 0; i < dsp->size; i += 3) {
688 image = dsp->data + i;
689 /* Wait DSP ready for a new read */
690 if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
691 printk("dsp loading error at position %d\n", i);
692 return err;
693 }
694 cptr = image;
695 csum ^= *cptr;
696 csum = (csum >> 24) | (csum << 8);
697 vx_outb(chip, TXH, *cptr++);
698 csum ^= *cptr;
699 csum = (csum >> 24) | (csum << 8);
700 vx_outb(chip, TXM, *cptr++);
701 csum ^= *cptr;
702 csum = (csum >> 24) | (csum << 8);
703 vx_outb(chip, TXL, *cptr++);
704 }
705 snd_printdd(KERN_DEBUG "checksum = 0x%08x\n", csum);
706
707 snd_vx_delay(chip, 200);
708
709 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
710 return err;
711
712 vx_toggle_dac_mute(chip, 0);
713
714 vx_test_and_ack(chip);
715 vx_validate_irq(chip, 1);
716
717 return 0;
718}
719
720#ifdef CONFIG_PM
721/*
722 * suspend
723 */
724static int snd_vx_suspend(snd_card_t *card, pm_message_t state)
725{
726 vx_core_t *chip = card->pm_private_data;
727 unsigned int i;
728
729 snd_assert(chip, return -EINVAL);
730
731 chip->chip_status |= VX_STAT_IN_SUSPEND;
732 for (i = 0; i < chip->hw->num_codecs; i++)
733 snd_pcm_suspend_all(chip->pcm[i]);
734
735 return 0;
736}
737
738/*
739 * resume
740 */
741static int snd_vx_resume(snd_card_t *card)
742{
743 vx_core_t *chip = card->pm_private_data;
744 int i, err;
745
746 snd_assert(chip, return -EINVAL);
747
748 chip->chip_status &= ~VX_STAT_CHIP_INIT;
749
750 for (i = 0; i < 4; i++) {
751 if (! chip->firmware[i])
752 continue;
753 err = chip->ops->load_dsp(chip, i, chip->firmware[i]);
754 if (err < 0) {
755 snd_printk(KERN_ERR "vx: firmware resume error at DSP %d\n", i);
756 return -EIO;
757 }
758 }
759
760 chip->chip_status |= VX_STAT_CHIP_INIT;
761 chip->chip_status &= ~VX_STAT_IN_SUSPEND;
762
763 return 0;
764}
765
766#endif
767
768/**
769 * snd_vx_create - constructor for vx_core_t
770 * @hw: hardware specific record
771 *
772 * this function allocates the instance and prepare for the hardware
773 * initialization.
774 *
775 * return the instance pointer if successful, NULL in error.
776 */
777vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
778 struct snd_vx_ops *ops,
779 int extra_size)
780{
781 vx_core_t *chip;
782
783 snd_assert(card && hw && ops, return NULL);
784
785 chip = kcalloc(1, sizeof(*chip) + extra_size, GFP_KERNEL);
786 if (! chip) {
787 snd_printk(KERN_ERR "vx_core: no memory\n");
788 return NULL;
789 }
790 spin_lock_init(&chip->lock);
791 spin_lock_init(&chip->irq_lock);
792 chip->irq = -1;
793 chip->hw = hw;
794 chip->type = hw->type;
795 chip->ops = ops;
796 tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip);
797 init_MUTEX(&chip->mixer_mutex);
798
799 chip->card = card;
800 card->private_data = chip;
801 strcpy(card->driver, hw->name);
802 sprintf(card->shortname, "Digigram %s", hw->name);
803
804 snd_card_set_pm_callback(card, snd_vx_suspend, snd_vx_resume, chip);
805
806 vx_proc_init(chip);
807
808 return chip;
809}
810
811/*
812 * module entries
813 */
814static int __init alsa_vx_core_init(void)
815{
816 return 0;
817}
818
819static void __exit alsa_vx_core_exit(void)
820{
821}
822
823module_init(alsa_vx_core_init)
824module_exit(alsa_vx_core_exit)
825
826/*
827 * exports
828 */
829EXPORT_SYMBOL(snd_vx_check_reg_bit);
830EXPORT_SYMBOL(snd_vx_create);
831EXPORT_SYMBOL(snd_vx_setup_firmware);
832EXPORT_SYMBOL(snd_vx_free_firmware);
833EXPORT_SYMBOL(snd_vx_irq_handler);
834EXPORT_SYMBOL(snd_vx_delay);
835EXPORT_SYMBOL(snd_vx_dsp_boot);
836EXPORT_SYMBOL(snd_vx_dsp_load);
837EXPORT_SYMBOL(snd_vx_load_boot_image);
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
new file mode 100644
index 000000000000..9a3dc3c3b3de
--- /dev/null
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -0,0 +1,249 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * DSP firmware management
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/device.h>
25#include <linux/firmware.h>
26#include <sound/core.h>
27#include <sound/hwdep.h>
28#include <sound/vx_core.h>
29
30#ifdef SND_VX_FW_LOADER
31
32int snd_vx_setup_firmware(vx_core_t *chip)
33{
34 static char *fw_files[VX_TYPE_NUMS][4] = {
35 [VX_TYPE_BOARD] = {
36 NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56",
37 },
38 [VX_TYPE_V2] = {
39 NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56",
40 },
41 [VX_TYPE_MIC] = {
42 NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56",
43 },
44 [VX_TYPE_VXPOCKET] = {
45 "bx_1_vxp.b56", "x1_1_vxp.xlx", "bd563s3.boot", "l_1_vxp.d56"
46 },
47 [VX_TYPE_VXP440] = {
48 "bx_1_vp4.b56", "x1_1_vp4.xlx", "bd563s3.boot", "l_1_vp4.d56"
49 },
50 };
51
52 int i, err;
53
54 for (i = 0; i < 4; i++) {
55 char path[32];
56 const struct firmware *fw;
57 if (! fw_files[chip->type][i])
58 continue;
59 sprintf(path, "vx/%s", fw_files[chip->type][i]);
60 if (request_firmware(&fw, path, chip->dev)) {
61 snd_printk(KERN_ERR "vx: can't load firmware %s\n", path);
62 return -ENOENT;
63 }
64 err = chip->ops->load_dsp(chip, i, fw);
65 if (err < 0) {
66 release_firmware(fw);
67 return err;
68 }
69 if (i == 1)
70 chip->chip_status |= VX_STAT_XILINX_LOADED;
71#ifdef CONFIG_PM
72 chip->firmware[i] = fw;
73#else
74 release_firmware(fw);
75#endif
76 }
77
78 /* ok, we reached to the last one */
79 /* create the devices if not built yet */
80 if ((err = snd_vx_pcm_new(chip)) < 0)
81 return err;
82
83 if ((err = snd_vx_mixer_new(chip)) < 0)
84 return err;
85
86 if (chip->ops->add_controls)
87 if ((err = chip->ops->add_controls(chip)) < 0)
88 return err;
89
90 chip->chip_status |= VX_STAT_DEVICE_INIT;
91 chip->chip_status |= VX_STAT_CHIP_INIT;
92
93 return snd_card_register(chip->card);
94}
95
96/* exported */
97void snd_vx_free_firmware(vx_core_t *chip)
98{
99#ifdef CONFIG_PM
100 int i;
101 for (i = 0; i < 4; i++)
102 release_firmware(chip->firmware[i]);
103#endif
104}
105
106#else /* old style firmware loading */
107
108static int vx_hwdep_open(snd_hwdep_t *hw, struct file *file)
109{
110 return 0;
111}
112
113static int vx_hwdep_release(snd_hwdep_t *hw, struct file *file)
114{
115 return 0;
116}
117
118static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
119{
120 static char *type_ids[VX_TYPE_NUMS] = {
121 [VX_TYPE_BOARD] = "vxboard",
122 [VX_TYPE_V2] = "vx222",
123 [VX_TYPE_MIC] = "vx222",
124 [VX_TYPE_VXPOCKET] = "vxpocket",
125 [VX_TYPE_VXP440] = "vxp440",
126 };
127 vx_core_t *vx = hw->private_data;
128
129 snd_assert(type_ids[vx->type], return -EINVAL);
130 strcpy(info->id, type_ids[vx->type]);
131 if (vx_is_pcmcia(vx))
132 info->num_dsps = 4;
133 else
134 info->num_dsps = 3;
135 if (vx->chip_status & VX_STAT_CHIP_INIT)
136 info->chip_ready = 1;
137 info->version = VX_DRIVER_VERSION;
138 return 0;
139}
140
141static void free_fw(const struct firmware *fw)
142{
143 if (fw) {
144 vfree(fw->data);
145 kfree(fw);
146 }
147}
148
149static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
150{
151 vx_core_t *vx = hw->private_data;
152 int index, err;
153 struct firmware *fw;
154
155 snd_assert(vx->ops->load_dsp, return -ENXIO);
156
157 fw = kmalloc(sizeof(*fw), GFP_KERNEL);
158 if (! fw) {
159 snd_printk(KERN_ERR "cannot allocate firmware\n");
160 return -ENOMEM;
161 }
162 fw->size = dsp->length;
163 fw->data = vmalloc(fw->size);
164 if (! fw->data) {
165 snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n",
166 (int)fw->size);
167 kfree(fw);
168 return -ENOMEM;
169 }
170 if (copy_from_user(fw->data, dsp->image, dsp->length)) {
171 free_fw(fw);
172 return -EFAULT;
173 }
174
175 index = dsp->index;
176 if (! vx_is_pcmcia(vx))
177 index++;
178 err = vx->ops->load_dsp(vx, index, fw);
179 if (err < 0) {
180 free_fw(fw);
181 return err;
182 }
183#ifdef CONFIG_PM
184 vx->firmware[index] = fw;
185#else
186 free_fw(fw);
187#endif
188
189 if (index == 1)
190 vx->chip_status |= VX_STAT_XILINX_LOADED;
191 if (index < 3)
192 return 0;
193
194 /* ok, we reached to the last one */
195 /* create the devices if not built yet */
196 if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) {
197 if ((err = snd_vx_pcm_new(vx)) < 0)
198 return err;
199
200 if ((err = snd_vx_mixer_new(vx)) < 0)
201 return err;
202
203 if (vx->ops->add_controls)
204 if ((err = vx->ops->add_controls(vx)) < 0)
205 return err;
206
207 if ((err = snd_card_register(vx->card)) < 0)
208 return err;
209
210 vx->chip_status |= VX_STAT_DEVICE_INIT;
211 }
212 vx->chip_status |= VX_STAT_CHIP_INIT;
213 return 0;
214}
215
216
217/* exported */
218int snd_vx_setup_firmware(vx_core_t *chip)
219{
220 int err;
221 snd_hwdep_t *hw;
222
223 if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
224 return err;
225
226 hw->iface = SNDRV_HWDEP_IFACE_VX;
227 hw->private_data = chip;
228 hw->ops.open = vx_hwdep_open;
229 hw->ops.release = vx_hwdep_release;
230 hw->ops.dsp_status = vx_hwdep_dsp_status;
231 hw->ops.dsp_load = vx_hwdep_dsp_load;
232 hw->exclusive = 1;
233 sprintf(hw->name, "VX Loader (%s)", chip->card->driver);
234 chip->hwdep = hw;
235
236 return snd_card_register(chip->card);
237}
238
239/* exported */
240void snd_vx_free_firmware(vx_core_t *chip)
241{
242#ifdef CONFIG_PM
243 int i;
244 for (i = 0; i < 4; i++)
245 free_fw(chip->firmware[i]);
246#endif
247}
248
249#endif /* SND_VX_FW_LOADER */
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
new file mode 100644
index 000000000000..f00c88886460
--- /dev/null
+++ b/sound/drivers/vx/vx_mixer.c
@@ -0,0 +1,1000 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * Common mixer part
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/control.h>
26#include <sound/vx_core.h>
27#include "vx_cmd.h"
28
29
30/*
31 * write a codec data (24bit)
32 */
33static void vx_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
34{
35 unsigned long flags;
36
37 snd_assert(chip->ops->write_codec, return);
38
39 if (chip->chip_status & VX_STAT_IS_STALE)
40 return;
41
42 spin_lock_irqsave(&chip->lock, flags);
43 chip->ops->write_codec(chip, codec, data);
44 spin_unlock_irqrestore(&chip->lock, flags);
45}
46
47/*
48 * Data type used to access the Codec
49 */
50typedef union {
51 u32 l;
52#ifdef SNDRV_BIG_ENDIAN
53 struct w {
54 u16 h;
55 u16 l;
56 } w;
57 struct b {
58 u8 hh;
59 u8 mh;
60 u8 ml;
61 u8 ll;
62 } b;
63#else /* LITTLE_ENDIAN */
64 struct w {
65 u16 l;
66 u16 h;
67 } w;
68 struct b {
69 u8 ll;
70 u8 ml;
71 u8 mh;
72 u8 hh;
73 } b;
74#endif
75} vx_codec_data_t;
76
77#define SET_CDC_DATA_SEL(di,s) ((di).b.mh = (u8) (s))
78#define SET_CDC_DATA_REG(di,r) ((di).b.ml = (u8) (r))
79#define SET_CDC_DATA_VAL(di,d) ((di).b.ll = (u8) (d))
80#define SET_CDC_DATA_INIT(di) ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR))
81
82/*
83 * set up codec register and write the value
84 * @codec: the codec id, 0 or 1
85 * @reg: register index
86 * @val: data value
87 */
88static void vx_set_codec_reg(vx_core_t *chip, int codec, int reg, int val)
89{
90 vx_codec_data_t data;
91 /* DAC control register */
92 SET_CDC_DATA_INIT(data);
93 SET_CDC_DATA_REG(data, reg);
94 SET_CDC_DATA_VAL(data, val);
95 vx_write_codec_reg(chip, codec, data.l);
96}
97
98
99/*
100 * vx_set_analog_output_level - set the output attenuation level
101 * @codec: the output codec, 0 or 1. (1 for VXP440 only)
102 * @left: left output level, 0 = mute
103 * @right: right output level
104 */
105static void vx_set_analog_output_level(vx_core_t *chip, int codec, int left, int right)
106{
107 left = chip->hw->output_level_max - left;
108 right = chip->hw->output_level_max - right;
109
110 if (chip->ops->akm_write) {
111 chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left);
112 chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
113 } else {
114 /* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */
115 vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left);
116 vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
117 }
118}
119
120
121/*
122 * vx_toggle_dac_mute - mute/unmute DAC
123 * @mute: 0 = unmute, 1 = mute
124 */
125
126#define DAC_ATTEN_MIN 0x08
127#define DAC_ATTEN_MAX 0x38
128
129void vx_toggle_dac_mute(vx_core_t *chip, int mute)
130{
131 unsigned int i;
132 for (i = 0; i < chip->hw->num_codecs; i++) {
133 if (chip->ops->akm_write)
134 chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */
135 else
136 vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER,
137 mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN);
138 }
139}
140
141/*
142 * vx_reset_codec - reset and initialize the codecs
143 */
144void vx_reset_codec(vx_core_t *chip, int cold_reset)
145{
146 unsigned int i;
147 int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65;
148
149 chip->ops->reset_codec(chip);
150
151 /* AKM codecs should be initialized in reset_codec callback */
152 if (! chip->ops->akm_write) {
153 /* initialize old codecs */
154 for (i = 0; i < chip->hw->num_codecs; i++) {
155 /* DAC control register (change level when zero crossing + mute) */
156 vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, DAC_ATTEN_MAX);
157 /* ADC control register */
158 vx_set_codec_reg(chip, i, XX_CODEC_ADC_CONTROL_REGISTER, 0x00);
159 /* Port mode register */
160 vx_set_codec_reg(chip, i, XX_CODEC_PORT_MODE_REGISTER, port);
161 /* Clock control register */
162 vx_set_codec_reg(chip, i, XX_CODEC_CLOCK_CONTROL_REGISTER, 0x00);
163 }
164 }
165
166 /* mute analog output */
167 for (i = 0; i < chip->hw->num_codecs; i++) {
168 chip->output_level[i][0] = 0;
169 chip->output_level[i][1] = 0;
170 vx_set_analog_output_level(chip, i, 0, 0);
171 }
172}
173
174/*
175 * change the audio input source
176 * @src: the target source (VX_AUDIO_SRC_XXX)
177 */
178static void vx_change_audio_source(vx_core_t *chip, int src)
179{
180 unsigned long flags;
181
182 if (chip->chip_status & VX_STAT_IS_STALE)
183 return;
184
185 spin_lock_irqsave(&chip->lock, flags);
186 chip->ops->change_audio_source(chip, src);
187 spin_unlock_irqrestore(&chip->lock, flags);
188}
189
190
191/*
192 * change the audio source if necessary and possible
193 * returns 1 if the source is actually changed.
194 */
195int vx_sync_audio_source(vx_core_t *chip)
196{
197 if (chip->audio_source_target == chip->audio_source ||
198 chip->pcm_running)
199 return 0;
200 vx_change_audio_source(chip, chip->audio_source_target);
201 chip->audio_source = chip->audio_source_target;
202 return 1;
203}
204
205
206/*
207 * audio level, mute, monitoring
208 */
209struct vx_audio_level {
210 unsigned int has_level: 1;
211 unsigned int has_monitor_level: 1;
212 unsigned int has_mute: 1;
213 unsigned int has_monitor_mute: 1;
214 unsigned int mute;
215 unsigned int monitor_mute;
216 short level;
217 short monitor_level;
218};
219
220static int vx_adjust_audio_level(vx_core_t *chip, int audio, int capture,
221 struct vx_audio_level *info)
222{
223 struct vx_rmh rmh;
224
225 if (chip->chip_status & VX_STAT_IS_STALE)
226 return -EBUSY;
227
228 vx_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
229 if (capture)
230 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
231 /* Add Audio IO mask */
232 rmh.Cmd[1] = 1 << audio;
233 rmh.Cmd[2] = 0;
234 if (info->has_level) {
235 rmh.Cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
236 rmh.Cmd[2] |= info->level;
237 }
238 if (info->has_monitor_level) {
239 rmh.Cmd[0] |= VALID_AUDIO_IO_MONITORING_LEVEL;
240 rmh.Cmd[2] |= ((unsigned int)info->monitor_level << 10);
241 }
242 if (info->has_mute) {
243 rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_LEVEL;
244 if (info->mute)
245 rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_LEVEL;
246 }
247 if (info->has_monitor_mute) {
248 /* validate flag for M2 at least to unmute it */
249 rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_MONITORING_1 | VALID_AUDIO_IO_MUTE_MONITORING_2;
250 if (info->monitor_mute)
251 rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_MONITORING_1;
252 }
253
254 return vx_send_msg(chip, &rmh);
255}
256
257
258#if 0 // not used
259static int vx_read_audio_level(vx_core_t *chip, int audio, int capture,
260 struct vx_audio_level *info)
261{
262 int err;
263 struct vx_rmh rmh;
264
265 memset(info, 0, sizeof(*info));
266 vx_init_rmh(&rmh, CMD_GET_AUDIO_LEVELS);
267 if (capture)
268 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
269 /* Add Audio IO mask */
270 rmh.Cmd[1] = 1 << audio;
271 err = vx_send_msg(chip, &rmh);
272 if (err < 0)
273 return err;
274 info.level = rmh.Stat[0] & MASK_DSP_WORD_LEVEL;
275 info.monitor_level = (rmh.Stat[0] >> 10) & MASK_DSP_WORD_LEVEL;
276 info.mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_LEVEL) ? 1 : 0;
277 info.monitor_mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_MONITORING_1) ? 1 : 0;
278 return 0;
279}
280#endif // not used
281
282/*
283 * set the monitoring level and mute state of the given audio
284 * no more static, because must be called from vx_pcm to demute monitoring
285 */
286int vx_set_monitor_level(vx_core_t *chip, int audio, int level, int active)
287{
288 struct vx_audio_level info;
289
290 memset(&info, 0, sizeof(info));
291 info.has_monitor_level = 1;
292 info.monitor_level = level;
293 info.has_monitor_mute = 1;
294 info.monitor_mute = !active;
295 chip->audio_monitor[audio] = level;
296 chip->audio_monitor_active[audio] = active;
297 return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
298}
299
300
301/*
302 * set the mute status of the given audio
303 */
304static int vx_set_audio_switch(vx_core_t *chip, int audio, int active)
305{
306 struct vx_audio_level info;
307
308 memset(&info, 0, sizeof(info));
309 info.has_mute = 1;
310 info.mute = !active;
311 chip->audio_active[audio] = active;
312 return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
313}
314
315/*
316 * set the mute status of the given audio
317 */
318static int vx_set_audio_gain(vx_core_t *chip, int audio, int capture, int level)
319{
320 struct vx_audio_level info;
321
322 memset(&info, 0, sizeof(info));
323 info.has_level = 1;
324 info.level = level;
325 chip->audio_gain[capture][audio] = level;
326 return vx_adjust_audio_level(chip, audio, capture, &info);
327}
328
329/*
330 * reset all audio levels
331 */
332static void vx_reset_audio_levels(vx_core_t *chip)
333{
334 unsigned int i, c;
335 struct vx_audio_level info;
336
337 memset(chip->audio_gain, 0, sizeof(chip->audio_gain));
338 memset(chip->audio_active, 0, sizeof(chip->audio_active));
339 memset(chip->audio_monitor, 0, sizeof(chip->audio_monitor));
340 memset(chip->audio_monitor_active, 0, sizeof(chip->audio_monitor_active));
341
342 for (c = 0; c < 2; c++) {
343 for (i = 0; i < chip->hw->num_ins * 2; i++) {
344 memset(&info, 0, sizeof(info));
345 if (c == 0) {
346 info.has_monitor_level = 1;
347 info.has_mute = 1;
348 info.has_monitor_mute = 1;
349 }
350 info.has_level = 1;
351 info.level = CVAL_0DB; /* default: 0dB */
352 vx_adjust_audio_level(chip, i, c, &info);
353 chip->audio_gain[c][i] = CVAL_0DB;
354 chip->audio_monitor[i] = CVAL_0DB;
355 }
356 }
357}
358
359
360/*
361 * VU, peak meter record
362 */
363
364#define VU_METER_CHANNELS 2
365
366struct vx_vu_meter {
367 int saturated;
368 int vu_level;
369 int peak_level;
370};
371
372/*
373 * get the VU and peak meter values
374 * @audio: the audio index
375 * @capture: 0 = playback, 1 = capture operation
376 * @info: the array of vx_vu_meter records (size = 2).
377 */
378static int vx_get_audio_vu_meter(vx_core_t *chip, int audio, int capture, struct vx_vu_meter *info)
379{
380 struct vx_rmh rmh;
381 int i, err;
382
383 if (chip->chip_status & VX_STAT_IS_STALE)
384 return -EBUSY;
385
386 vx_init_rmh(&rmh, CMD_AUDIO_VU_PIC_METER);
387 rmh.LgStat += 2 * VU_METER_CHANNELS;
388 if (capture)
389 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
390
391 /* Add Audio IO mask */
392 rmh.Cmd[1] = 0;
393 for (i = 0; i < VU_METER_CHANNELS; i++)
394 rmh.Cmd[1] |= 1 << (audio + i);
395 err = vx_send_msg(chip, &rmh);
396 if (err < 0)
397 return err;
398 /* Read response */
399 for (i = 0; i < 2 * VU_METER_CHANNELS; i +=2) {
400 info->saturated = (rmh.Stat[0] & (1 << (audio + i))) ? 1 : 0;
401 info->vu_level = rmh.Stat[i + 1];
402 info->peak_level = rmh.Stat[i + 2];
403 info++;
404 }
405 return 0;
406}
407
408
409/*
410 * control API entries
411 */
412
413/*
414 * output level control
415 */
416static int vx_output_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
417{
418 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
419 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
420 uinfo->count = 2;
421 uinfo->value.integer.min = 0;
422 uinfo->value.integer.max = chip->hw->output_level_max;
423 return 0;
424}
425
426static int vx_output_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
427{
428 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
429 int codec = kcontrol->id.index;
430 down(&chip->mixer_mutex);
431 ucontrol->value.integer.value[0] = chip->output_level[codec][0];
432 ucontrol->value.integer.value[1] = chip->output_level[codec][1];
433 up(&chip->mixer_mutex);
434 return 0;
435}
436
437static int vx_output_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
438{
439 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
440 int codec = kcontrol->id.index;
441 down(&chip->mixer_mutex);
442 if (ucontrol->value.integer.value[0] != chip->output_level[codec][0] ||
443 ucontrol->value.integer.value[1] != chip->output_level[codec][1]) {
444 vx_set_analog_output_level(chip, codec,
445 ucontrol->value.integer.value[0],
446 ucontrol->value.integer.value[1]);
447 chip->output_level[codec][0] = ucontrol->value.integer.value[0];
448 chip->output_level[codec][1] = ucontrol->value.integer.value[1];
449 up(&chip->mixer_mutex);
450 return 1;
451 }
452 up(&chip->mixer_mutex);
453 return 0;
454}
455
456static snd_kcontrol_new_t vx_control_output_level = {
457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
458 .name = "Master Playback Volume",
459 .info = vx_output_level_info,
460 .get = vx_output_level_get,
461 .put = vx_output_level_put,
462};
463
464/*
465 * audio source select
466 */
467static int vx_audio_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
468{
469 static char *texts_mic[3] = {
470 "Digital", "Line", "Mic"
471 };
472 static char *texts_vx2[2] = {
473 "Digital", "Analog"
474 };
475 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
476
477 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
478 uinfo->count = 1;
479 if (chip->type >= VX_TYPE_VXPOCKET) {
480 uinfo->value.enumerated.items = 3;
481 if (uinfo->value.enumerated.item > 2)
482 uinfo->value.enumerated.item = 2;
483 strcpy(uinfo->value.enumerated.name,
484 texts_mic[uinfo->value.enumerated.item]);
485 } else {
486 uinfo->value.enumerated.items = 2;
487 if (uinfo->value.enumerated.item > 1)
488 uinfo->value.enumerated.item = 1;
489 strcpy(uinfo->value.enumerated.name,
490 texts_vx2[uinfo->value.enumerated.item]);
491 }
492 return 0;
493}
494
495static int vx_audio_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
496{
497 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
498 ucontrol->value.enumerated.item[0] = chip->audio_source_target;
499 return 0;
500}
501
502static int vx_audio_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
503{
504 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
505 down(&chip->mixer_mutex);
506 if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) {
507 chip->audio_source_target = ucontrol->value.enumerated.item[0];
508 vx_sync_audio_source(chip);
509 up(&chip->mixer_mutex);
510 return 1;
511 }
512 up(&chip->mixer_mutex);
513 return 0;
514}
515
516static snd_kcontrol_new_t vx_control_audio_src = {
517 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
518 .name = "Capture Source",
519 .info = vx_audio_src_info,
520 .get = vx_audio_src_get,
521 .put = vx_audio_src_put,
522};
523
524/*
525 * clock mode selection
526 */
527static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
528{
529 static char *texts[3] = {
530 "Auto", "Internal", "External"
531 };
532
533 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
534 uinfo->count = 1;
535 uinfo->value.enumerated.items = 3;
536 if (uinfo->value.enumerated.item > 2)
537 uinfo->value.enumerated.item = 2;
538 strcpy(uinfo->value.enumerated.name,
539 texts[uinfo->value.enumerated.item]);
540 return 0;
541}
542
543static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
544{
545 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
546 ucontrol->value.enumerated.item[0] = chip->clock_mode;
547 return 0;
548}
549
550static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
551{
552 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
553 down(&chip->mixer_mutex);
554 if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
555 chip->clock_mode = ucontrol->value.enumerated.item[0];
556 vx_set_clock(chip, chip->freq);
557 up(&chip->mixer_mutex);
558 return 1;
559 }
560 up(&chip->mixer_mutex);
561 return 0;
562}
563
564static snd_kcontrol_new_t vx_control_clock_mode = {
565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
566 .name = "Clock Mode",
567 .info = vx_clock_mode_info,
568 .get = vx_clock_mode_get,
569 .put = vx_clock_mode_put,
570};
571
572/*
573 * Audio Gain
574 */
575static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
576{
577 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
578 uinfo->count = 2;
579 uinfo->value.integer.min = 0;
580 uinfo->value.integer.max = CVAL_MAX;
581 return 0;
582}
583
584static int vx_audio_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
585{
586 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
587 int audio = kcontrol->private_value & 0xff;
588 int capture = (kcontrol->private_value >> 8) & 1;
589
590 down(&chip->mixer_mutex);
591 ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio];
592 ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1];
593 up(&chip->mixer_mutex);
594 return 0;
595}
596
597static int vx_audio_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
598{
599 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
600 int audio = kcontrol->private_value & 0xff;
601 int capture = (kcontrol->private_value >> 8) & 1;
602
603 down(&chip->mixer_mutex);
604 if (ucontrol->value.integer.value[0] != chip->audio_gain[capture][audio] ||
605 ucontrol->value.integer.value[1] != chip->audio_gain[capture][audio+1]) {
606 vx_set_audio_gain(chip, audio, capture, ucontrol->value.integer.value[0]);
607 vx_set_audio_gain(chip, audio+1, capture, ucontrol->value.integer.value[1]);
608 up(&chip->mixer_mutex);
609 return 1;
610 }
611 up(&chip->mixer_mutex);
612 return 0;
613}
614
615static int vx_audio_monitor_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
616{
617 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
618 int audio = kcontrol->private_value & 0xff;
619
620 down(&chip->mixer_mutex);
621 ucontrol->value.integer.value[0] = chip->audio_monitor[audio];
622 ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1];
623 up(&chip->mixer_mutex);
624 return 0;
625}
626
627static int vx_audio_monitor_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
628{
629 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
630 int audio = kcontrol->private_value & 0xff;
631
632 down(&chip->mixer_mutex);
633 if (ucontrol->value.integer.value[0] != chip->audio_monitor[audio] ||
634 ucontrol->value.integer.value[1] != chip->audio_monitor[audio+1]) {
635 vx_set_monitor_level(chip, audio, ucontrol->value.integer.value[0],
636 chip->audio_monitor_active[audio]);
637 vx_set_monitor_level(chip, audio+1, ucontrol->value.integer.value[1],
638 chip->audio_monitor_active[audio+1]);
639 up(&chip->mixer_mutex);
640 return 1;
641 }
642 up(&chip->mixer_mutex);
643 return 0;
644}
645
646static int vx_audio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
647{
648 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
649 uinfo->count = 2;
650 uinfo->value.integer.min = 0;
651 uinfo->value.integer.max = 1;
652 return 0;
653}
654
655static int vx_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
656{
657 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
658 int audio = kcontrol->private_value & 0xff;
659
660 down(&chip->mixer_mutex);
661 ucontrol->value.integer.value[0] = chip->audio_active[audio];
662 ucontrol->value.integer.value[1] = chip->audio_active[audio+1];
663 up(&chip->mixer_mutex);
664 return 0;
665}
666
667static int vx_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
668{
669 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
670 int audio = kcontrol->private_value & 0xff;
671
672 down(&chip->mixer_mutex);
673 if (ucontrol->value.integer.value[0] != chip->audio_active[audio] ||
674 ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) {
675 vx_set_audio_switch(chip, audio, ucontrol->value.integer.value[0]);
676 vx_set_audio_switch(chip, audio+1, ucontrol->value.integer.value[1]);
677 up(&chip->mixer_mutex);
678 return 1;
679 }
680 up(&chip->mixer_mutex);
681 return 0;
682}
683
684static int vx_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
685{
686 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
687 int audio = kcontrol->private_value & 0xff;
688
689 down(&chip->mixer_mutex);
690 ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio];
691 ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1];
692 up(&chip->mixer_mutex);
693 return 0;
694}
695
696static int vx_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
697{
698 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
699 int audio = kcontrol->private_value & 0xff;
700
701 down(&chip->mixer_mutex);
702 if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] ||
703 ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) {
704 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
705 ucontrol->value.integer.value[0]);
706 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
707 ucontrol->value.integer.value[1]);
708 up(&chip->mixer_mutex);
709 return 1;
710 }
711 up(&chip->mixer_mutex);
712 return 0;
713}
714
715static snd_kcontrol_new_t vx_control_audio_gain = {
716 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
717 /* name will be filled later */
718 .info = vx_audio_gain_info,
719 .get = vx_audio_gain_get,
720 .put = vx_audio_gain_put
721};
722static snd_kcontrol_new_t vx_control_output_switch = {
723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
724 .name = "PCM Playback Switch",
725 .info = vx_audio_sw_info,
726 .get = vx_audio_sw_get,
727 .put = vx_audio_sw_put
728};
729static snd_kcontrol_new_t vx_control_monitor_gain = {
730 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
731 .name = "Monitoring Volume",
732 .info = vx_audio_gain_info, /* shared */
733 .get = vx_audio_monitor_get,
734 .put = vx_audio_monitor_put
735};
736static snd_kcontrol_new_t vx_control_monitor_switch = {
737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
738 .name = "Monitoring Switch",
739 .info = vx_audio_sw_info, /* shared */
740 .get = vx_monitor_sw_get,
741 .put = vx_monitor_sw_put
742};
743
744
745/*
746 * IEC958 status bits
747 */
748static int vx_iec958_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
749{
750 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
751 uinfo->count = 1;
752 return 0;
753}
754
755static int vx_iec958_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
756{
757 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
758
759 down(&chip->mixer_mutex);
760 ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff;
761 ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff;
762 ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff;
763 ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff;
764 up(&chip->mixer_mutex);
765 return 0;
766}
767
768static int vx_iec958_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
769{
770 ucontrol->value.iec958.status[0] = 0xff;
771 ucontrol->value.iec958.status[1] = 0xff;
772 ucontrol->value.iec958.status[2] = 0xff;
773 ucontrol->value.iec958.status[3] = 0xff;
774 return 0;
775}
776
777static int vx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
778{
779 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
780 unsigned int val;
781
782 val = (ucontrol->value.iec958.status[0] << 0) |
783 (ucontrol->value.iec958.status[1] << 8) |
784 (ucontrol->value.iec958.status[2] << 16) |
785 (ucontrol->value.iec958.status[3] << 24);
786 down(&chip->mixer_mutex);
787 if (chip->uer_bits != val) {
788 chip->uer_bits = val;
789 vx_set_iec958_status(chip, val);
790 up(&chip->mixer_mutex);
791 return 1;
792 }
793 up(&chip->mixer_mutex);
794 return 0;
795}
796
797static snd_kcontrol_new_t vx_control_iec958_mask = {
798 .access = SNDRV_CTL_ELEM_ACCESS_READ,
799 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
800 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
801 .info = vx_iec958_info, /* shared */
802 .get = vx_iec958_mask_get,
803};
804
805static snd_kcontrol_new_t vx_control_iec958 = {
806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
807 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
808 .info = vx_iec958_info,
809 .get = vx_iec958_get,
810 .put = vx_iec958_put
811};
812
813
814/*
815 * VU meter
816 */
817
818#define METER_MAX 0xff
819#define METER_SHIFT 16
820
821static int vx_vu_meter_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
822{
823 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
824 uinfo->count = 2;
825 uinfo->value.integer.min = 0;
826 uinfo->value.integer.max = METER_MAX;
827 return 0;
828}
829
830static int vx_vu_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
831{
832 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
833 struct vx_vu_meter meter[2];
834 int audio = kcontrol->private_value & 0xff;
835 int capture = (kcontrol->private_value >> 8) & 1;
836
837 vx_get_audio_vu_meter(chip, audio, capture, meter);
838 ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT;
839 ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT;
840 return 0;
841}
842
843static int vx_peak_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
844{
845 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
846 struct vx_vu_meter meter[2];
847 int audio = kcontrol->private_value & 0xff;
848 int capture = (kcontrol->private_value >> 8) & 1;
849
850 vx_get_audio_vu_meter(chip, audio, capture, meter);
851 ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT;
852 ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT;
853 return 0;
854}
855
856static int vx_saturation_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
857{
858 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
859 uinfo->count = 2;
860 uinfo->value.integer.min = 0;
861 uinfo->value.integer.max = 1;
862 return 0;
863}
864
865static int vx_saturation_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
866{
867 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
868 struct vx_vu_meter meter[2];
869 int audio = kcontrol->private_value & 0xff;
870
871 vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */
872 ucontrol->value.integer.value[0] = meter[0].saturated;
873 ucontrol->value.integer.value[1] = meter[1].saturated;
874 return 0;
875}
876
877static snd_kcontrol_new_t vx_control_vu_meter = {
878 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
879 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
880 /* name will be filled later */
881 .info = vx_vu_meter_info,
882 .get = vx_vu_meter_get,
883};
884
885static snd_kcontrol_new_t vx_control_peak_meter = {
886 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
887 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
888 /* name will be filled later */
889 .info = vx_vu_meter_info, /* shared */
890 .get = vx_peak_meter_get,
891};
892
893static snd_kcontrol_new_t vx_control_saturation = {
894 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
895 .name = "Input Saturation",
896 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
897 .info = vx_saturation_info,
898 .get = vx_saturation_get,
899};
900
901
902
903/*
904 *
905 */
906
907int snd_vx_mixer_new(vx_core_t *chip)
908{
909 unsigned int i, c;
910 int err;
911 snd_kcontrol_new_t temp;
912 snd_card_t *card = chip->card;
913 char name[32];
914
915 strcpy(card->mixername, card->driver);
916
917 /* output level controls */
918 for (i = 0; i < chip->hw->num_outs; i++) {
919 temp = vx_control_output_level;
920 temp.index = i;
921 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
922 return err;
923 }
924
925 /* PCM volumes, switches, monitoring */
926 for (i = 0; i < chip->hw->num_outs; i++) {
927 int val = i * 2;
928 temp = vx_control_audio_gain;
929 temp.index = i;
930 temp.name = "PCM Playback Volume";
931 temp.private_value = val;
932 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
933 return err;
934 temp = vx_control_output_switch;
935 temp.index = i;
936 temp.private_value = val;
937 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
938 return err;
939 temp = vx_control_monitor_gain;
940 temp.index = i;
941 temp.private_value = val;
942 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
943 return err;
944 temp = vx_control_monitor_switch;
945 temp.index = i;
946 temp.private_value = val;
947 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
948 return err;
949 }
950 for (i = 0; i < chip->hw->num_outs; i++) {
951 temp = vx_control_audio_gain;
952 temp.index = i;
953 temp.name = "PCM Capture Volume";
954 temp.private_value = (i * 2) | (1 << 8);
955 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
956 return err;
957 }
958
959 /* Audio source */
960 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
961 return err;
962 /* clock mode */
963 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
964 return err;
965 /* IEC958 controls */
966 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
967 return err;
968 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0)
969 return err;
970 /* VU, peak, saturation meters */
971 for (c = 0; c < 2; c++) {
972 static char *dir[2] = { "Output", "Input" };
973 for (i = 0; i < chip->hw->num_ins; i++) {
974 int val = (i * 2) | (c << 8);
975 if (c == 1) {
976 temp = vx_control_saturation;
977 temp.index = i;
978 temp.private_value = val;
979 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
980 return err;
981 }
982 sprintf(name, "%s VU Meter", dir[c]);
983 temp = vx_control_vu_meter;
984 temp.index = i;
985 temp.name = name;
986 temp.private_value = val;
987 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
988 return err;
989 sprintf(name, "%s Peak Meter", dir[c]);
990 temp = vx_control_peak_meter;
991 temp.index = i;
992 temp.name = name;
993 temp.private_value = val;
994 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
995 return err;
996 }
997 }
998 vx_reset_audio_levels(chip);
999 return 0;
1000}
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
new file mode 100644
index 000000000000..98587176b327
--- /dev/null
+++ b/sound/drivers/vx/vx_pcm.c
@@ -0,0 +1,1312 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * PCM part
5 *
6 * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 *
23 * STRATEGY
24 * for playback, we send series of "chunks", which size is equal with the
25 * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer
26 * interrupt is notified, and the interrupt handler will feed the next chunk.
27 *
28 * the current position is calculated from the sample count RMH.
29 * pipe->transferred is the counter of data which has been already transferred.
30 * if this counter reaches to the period size, snd_pcm_period_elapsed() will
31 * be issued.
32 *
33 * for capture, the situation is much easier.
34 * to get a low latency response, we'll check the capture streams at each
35 * interrupt (capture stream has no EOB notification). if the pending
36 * data is accumulated to the period size, snd_pcm_period_elapsed() is
37 * called and the pointer is updated.
38 *
39 * the current point of read buffer is kept in pipe->hw_ptr. note that
40 * this is in bytes.
41 *
42 *
43 * TODO
44 * - linked trigger for full-duplex mode.
45 * - scheduled action on the stream.
46 */
47
48#include <sound/driver.h>
49#include <linux/slab.h>
50#include <linux/vmalloc.h>
51#include <linux/delay.h>
52#include <sound/core.h>
53#include <sound/asoundef.h>
54#include <sound/pcm.h>
55#include <sound/vx_core.h>
56#include "vx_cmd.h"
57
58
59/*
60 * we use a vmalloc'ed (sg-)buffer
61 */
62
63/* get the physical page pointer on the given offset */
64static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, unsigned long offset)
65{
66 void *pageptr = subs->runtime->dma_area + offset;
67 return vmalloc_to_page(pageptr);
68}
69
70/*
71 * allocate a buffer via vmalloc_32().
72 * called from hw_params
73 * NOTE: this may be called not only once per pcm open!
74 */
75static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
76{
77 snd_pcm_runtime_t *runtime = subs->runtime;
78 if (runtime->dma_area) {
79 /* already allocated */
80 if (runtime->dma_bytes >= size)
81 return 0; /* already enough large */
82 vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */
83 }
84 runtime->dma_area = vmalloc_32(size);
85 if (! runtime->dma_area)
86 return -ENOMEM;
87 memset(runtime->dma_area, 0, size);
88 runtime->dma_bytes = size;
89 return 1; /* changed */
90}
91
92/*
93 * free the buffer.
94 * called from hw_free callback
95 * NOTE: this may be called not only once per pcm open!
96 */
97static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
98{
99 snd_pcm_runtime_t *runtime = subs->runtime;
100 if (runtime->dma_area) {
101 vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */
102 runtime->dma_area = NULL;
103 }
104 return 0;
105}
106
107
108/*
109 * read three pending pcm bytes via inb()
110 */
111static void vx_pcm_read_per_bytes(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe)
112{
113 int offset = pipe->hw_ptr;
114 unsigned char *buf = (unsigned char *)(runtime->dma_area + offset);
115 *buf++ = vx_inb(chip, RXH);
116 if (++offset >= pipe->buffer_bytes) {
117 offset = 0;
118 buf = (unsigned char *)runtime->dma_area;
119 }
120 *buf++ = vx_inb(chip, RXM);
121 if (++offset >= pipe->buffer_bytes) {
122 offset = 0;
123 buf = (unsigned char *)runtime->dma_area;
124 }
125 *buf++ = vx_inb(chip, RXL);
126 if (++offset >= pipe->buffer_bytes) {
127 offset = 0;
128 buf = (unsigned char *)runtime->dma_area;
129 }
130 pipe->hw_ptr = offset;
131}
132
133/*
134 * vx_set_pcx_time - convert from the PC time to the RMH status time.
135 * @pc_time: the pointer for the PC-time to set
136 * @dsp_time: the pointer for RMH status time array
137 */
138static void vx_set_pcx_time(vx_core_t *chip, pcx_time_t *pc_time, unsigned int *dsp_time)
139{
140 dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK;
141 dsp_time[1] = (unsigned int)(*pc_time) & MASK_DSP_WORD;
142}
143
144/*
145 * vx_set_differed_time - set the differed time if specified
146 * @rmh: the rmh record to modify
147 * @pipe: the pipe to be checked
148 *
149 * if the pipe is programmed with the differed time, set the DSP time
150 * on the rmh and changes its command length.
151 *
152 * returns the increase of the command length.
153 */
154static int vx_set_differed_time(vx_core_t *chip, struct vx_rmh *rmh, vx_pipe_t *pipe)
155{
156 /* Update The length added to the RMH command by the timestamp */
157 if (! (pipe->differed_type & DC_DIFFERED_DELAY))
158 return 0;
159
160 /* Set the T bit */
161 rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK;
162
163 /* Time stamp is the 1st following parameter */
164 vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]);
165
166 /* Add the flags to a notified differed command */
167 if (pipe->differed_type & DC_NOTIFY_DELAY)
168 rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ;
169
170 /* Add the flags to a multiple differed command */
171 if (pipe->differed_type & DC_MULTIPLE_DELAY)
172 rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH;
173
174 /* Add the flags to a stream-time differed command */
175 if (pipe->differed_type & DC_STREAM_TIME_DELAY)
176 rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH;
177
178 rmh->LgCmd += 2;
179 return 2;
180}
181
182/*
183 * vx_set_stream_format - send the stream format command
184 * @pipe: the affected pipe
185 * @data: format bitmask
186 */
187static int vx_set_stream_format(vx_core_t *chip, vx_pipe_t *pipe, unsigned int data)
188{
189 struct vx_rmh rmh;
190
191 vx_init_rmh(&rmh, pipe->is_capture ?
192 CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
193 rmh.Cmd[0] |= pipe->number << FIELD_SIZE;
194
195 /* Command might be longer since we may have to add a timestamp */
196 vx_set_differed_time(chip, &rmh, pipe);
197
198 rmh.Cmd[rmh.LgCmd] = (data & 0xFFFFFF00) >> 8;
199 rmh.Cmd[rmh.LgCmd + 1] = (data & 0xFF) << 16 /*| (datal & 0xFFFF00) >> 8*/;
200 rmh.LgCmd += 2;
201
202 return vx_send_msg(chip, &rmh);
203}
204
205
206/*
207 * vx_set_format - set the format of a pipe
208 * @pipe: the affected pipe
209 * @runtime: pcm runtime instance to be referred
210 *
211 * returns 0 if successful, or a negative error code.
212 */
213static int vx_set_format(vx_core_t *chip, vx_pipe_t *pipe,
214 snd_pcm_runtime_t *runtime)
215{
216 unsigned int header = HEADER_FMT_BASE;
217
218 if (runtime->channels == 1)
219 header |= HEADER_FMT_MONO;
220 if (snd_pcm_format_little_endian(runtime->format))
221 header |= HEADER_FMT_INTEL;
222 if (runtime->rate < 32000 && runtime->rate > 11025)
223 header |= HEADER_FMT_UPTO32;
224 else if (runtime->rate <= 11025)
225 header |= HEADER_FMT_UPTO11;
226
227 switch (snd_pcm_format_physical_width(runtime->format)) {
228 // case 8: break;
229 case 16: header |= HEADER_FMT_16BITS; break;
230 case 24: header |= HEADER_FMT_24BITS; break;
231 default :
232 snd_BUG();
233 return -EINVAL;
234 };
235
236 return vx_set_stream_format(chip, pipe, header);
237}
238
239/*
240 * set / query the IBL size
241 */
242static int vx_set_ibl(vx_core_t *chip, struct vx_ibl_info *info)
243{
244 int err;
245 struct vx_rmh rmh;
246
247 vx_init_rmh(&rmh, CMD_IBL);
248 rmh.Cmd[0] |= info->size & 0x03ffff;
249 err = vx_send_msg(chip, &rmh);
250 if (err < 0)
251 return err;
252 info->size = rmh.Stat[0];
253 info->max_size = rmh.Stat[1];
254 info->min_size = rmh.Stat[2];
255 info->granularity = rmh.Stat[3];
256 snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n",
257 info->size, info->max_size, info->min_size, info->granularity);
258 return 0;
259}
260
261
262/*
263 * vx_get_pipe_state - get the state of a pipe
264 * @pipe: the pipe to be checked
265 * @state: the pointer for the returned state
266 *
267 * checks the state of a given pipe, and stores the state (1 = running,
268 * 0 = paused) on the given pointer.
269 *
270 * called from trigger callback only
271 */
272static int vx_get_pipe_state(vx_core_t *chip, vx_pipe_t *pipe, int *state)
273{
274 int err;
275 struct vx_rmh rmh;
276
277 vx_init_rmh(&rmh, CMD_PIPE_STATE);
278 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
279 err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
280 if (! err)
281 *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
282 return err;
283}
284
285
286/*
287 * vx_query_hbuffer_size - query available h-buffer size in bytes
288 * @pipe: the pipe to be checked
289 *
290 * return the available size on h-buffer in bytes,
291 * or a negative error code.
292 *
293 * NOTE: calling this function always switches to the stream mode.
294 * you'll need to disconnect the host to get back to the
295 * normal mode.
296 */
297static int vx_query_hbuffer_size(vx_core_t *chip, vx_pipe_t *pipe)
298{
299 int result;
300 struct vx_rmh rmh;
301
302 vx_init_rmh(&rmh, CMD_SIZE_HBUFFER);
303 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
304 if (pipe->is_capture)
305 rmh.Cmd[0] |= 0x00000001;
306 result = vx_send_msg(chip, &rmh);
307 if (! result)
308 result = rmh.Stat[0] & 0xffff;
309 return result;
310}
311
312
313/*
314 * vx_pipe_can_start - query whether a pipe is ready for start
315 * @pipe: the pipe to be checked
316 *
317 * return 1 if ready, 0 if not ready, and negative value on error.
318 *
319 * called from trigger callback only
320 */
321static int vx_pipe_can_start(vx_core_t *chip, vx_pipe_t *pipe)
322{
323 int err;
324 struct vx_rmh rmh;
325
326 vx_init_rmh(&rmh, CMD_CAN_START_PIPE);
327 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
328 rmh.Cmd[0] |= 1;
329
330 err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
331 if (! err) {
332 if (rmh.Stat[0])
333 err = 1;
334 }
335 return err;
336}
337
338/*
339 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
340 * @pipe: the pipe to be configured
341 */
342static int vx_conf_pipe(vx_core_t *chip, vx_pipe_t *pipe)
343{
344 struct vx_rmh rmh;
345
346 vx_init_rmh(&rmh, CMD_CONF_PIPE);
347 if (pipe->is_capture)
348 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
349 rmh.Cmd[1] = 1 << pipe->number;
350 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
351}
352
353/*
354 * vx_send_irqa - trigger IRQA
355 */
356static int vx_send_irqa(vx_core_t *chip)
357{
358 struct vx_rmh rmh;
359
360 vx_init_rmh(&rmh, CMD_SEND_IRQA);
361 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
362}
363
364
365#define MAX_WAIT_FOR_DSP 250
366/*
367 * vx boards do not support inter-card sync, besides
368 * only 126 samples require to be prepared before a pipe can start
369 */
370#define CAN_START_DELAY 2 /* wait 2ms only before asking if the pipe is ready*/
371#define WAIT_STATE_DELAY 2 /* wait 2ms after irqA was requested and check if the pipe state toggled*/
372
373/*
374 * vx_toggle_pipe - start / pause a pipe
375 * @pipe: the pipe to be triggered
376 * @state: start = 1, pause = 0
377 *
378 * called from trigger callback only
379 *
380 */
381static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
382{
383 int err, i, cur_state;
384
385 /* Check the pipe is not already in the requested state */
386 if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
387 return -EBADFD;
388 if (state == cur_state)
389 return 0;
390
391 /* If a start is requested, ask the DSP to get prepared
392 * and wait for a positive acknowledge (when there are
393 * enough sound buffer for this pipe)
394 */
395 if (state) {
396 for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
397 err = vx_pipe_can_start(chip, pipe);
398 if (err > 0)
399 break;
400 /* Wait for a few, before asking again
401 * to avoid flooding the DSP with our requests
402 */
403 mdelay(1);
404 }
405 }
406
407 if ((err = vx_conf_pipe(chip, pipe)) < 0)
408 return err;
409
410 if ((err = vx_send_irqa(chip)) < 0)
411 return err;
412
413 /* If it completes successfully, wait for the pipes
414 * reaching the expected state before returning
415 * Check one pipe only (since they are synchronous)
416 */
417 for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
418 err = vx_get_pipe_state(chip, pipe, &cur_state);
419 if (err < 0 || cur_state == state)
420 break;
421 err = -EIO;
422 mdelay(1);
423 }
424 return err < 0 ? -EIO : 0;
425}
426
427
428/*
429 * vx_stop_pipe - stop a pipe
430 * @pipe: the pipe to be stopped
431 *
432 * called from trigger callback only
433 */
434static int vx_stop_pipe(vx_core_t *chip, vx_pipe_t *pipe)
435{
436 struct vx_rmh rmh;
437 vx_init_rmh(&rmh, CMD_STOP_PIPE);
438 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
439 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
440}
441
442
443/*
444 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance
445 * @capture: 0 = playback, 1 = capture operation
446 * @audioid: the audio id to be assigned
447 * @num_audio: number of audio channels
448 * @pipep: the returned pipe instance
449 *
450 * return 0 on success, or a negative error code.
451 */
452static int vx_alloc_pipe(vx_core_t *chip, int capture,
453 int audioid, int num_audio,
454 vx_pipe_t **pipep)
455{
456 int err;
457 vx_pipe_t *pipe;
458 struct vx_rmh rmh;
459 int data_mode;
460
461 *pipep = NULL;
462 vx_init_rmh(&rmh, CMD_RES_PIPE);
463 vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio);
464#if 0 // NYI
465 if (underrun_skip_sound)
466 rmh.Cmd[0] |= BIT_SKIP_SOUND;
467#endif // NYI
468 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
469 if (! capture && data_mode)
470 rmh.Cmd[0] |= BIT_DATA_MODE;
471 err = vx_send_msg(chip, &rmh);
472 if (err < 0)
473 return err;
474
475 /* initialize the pipe record */
476 pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
477 if (! pipe) {
478 /* release the pipe */
479 vx_init_rmh(&rmh, CMD_FREE_PIPE);
480 vx_set_pipe_cmd_params(&rmh, capture, audioid, 0);
481 vx_send_msg(chip, &rmh);
482 return -ENOMEM;
483 }
484
485 /* the pipe index should be identical with the audio index */
486 pipe->number = audioid;
487 pipe->is_capture = capture;
488 pipe->channels = num_audio;
489 pipe->differed_type = 0;
490 pipe->pcx_time = 0;
491 pipe->data_mode = data_mode;
492 *pipep = pipe;
493
494 return 0;
495}
496
497
498/*
499 * vx_free_pipe - release a pipe
500 * @pipe: pipe to be released
501 */
502static int vx_free_pipe(vx_core_t *chip, vx_pipe_t *pipe)
503{
504 struct vx_rmh rmh;
505
506 vx_init_rmh(&rmh, CMD_FREE_PIPE);
507 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
508 vx_send_msg(chip, &rmh);
509
510 kfree(pipe);
511 return 0;
512}
513
514
515/*
516 * vx_start_stream - start the stream
517 *
518 * called from trigger callback only
519 */
520static int vx_start_stream(vx_core_t *chip, vx_pipe_t *pipe)
521{
522 struct vx_rmh rmh;
523
524 vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
525 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
526 vx_set_differed_time(chip, &rmh, pipe);
527 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
528}
529
530
531/*
532 * vx_stop_stream - stop the stream
533 *
534 * called from trigger callback only
535 */
536static int vx_stop_stream(vx_core_t *chip, vx_pipe_t *pipe)
537{
538 struct vx_rmh rmh;
539
540 vx_init_rmh(&rmh, CMD_STOP_STREAM);
541 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
542 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
543}
544
545
546/*
547 * playback hw information
548 */
549
550static snd_pcm_hardware_t vx_pcm_playback_hw = {
551 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
552 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID |
553 SNDRV_PCM_INFO_RESUME),
554 .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
555 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
556 .rate_min = 5000,
557 .rate_max = 48000,
558 .channels_min = 1,
559 .channels_max = 2,
560 .buffer_bytes_max = (128*1024),
561 .period_bytes_min = 126,
562 .period_bytes_max = (128*1024),
563 .periods_min = 2,
564 .periods_max = VX_MAX_PERIODS,
565 .fifo_size = 126,
566};
567
568
569static void vx_pcm_delayed_start(unsigned long arg);
570
571/*
572 * vx_pcm_playback_open - open callback for playback
573 */
574static int vx_pcm_playback_open(snd_pcm_substream_t *subs)
575{
576 snd_pcm_runtime_t *runtime = subs->runtime;
577 vx_core_t *chip = snd_pcm_substream_chip(subs);
578 vx_pipe_t *pipe = NULL;
579 unsigned int audio;
580 int err;
581
582 if (chip->chip_status & VX_STAT_IS_STALE)
583 return -EBUSY;
584
585 audio = subs->pcm->device * 2;
586 snd_assert(audio < chip->audio_outs, return -EINVAL);
587
588 /* playback pipe may have been already allocated for monitoring */
589 pipe = chip->playback_pipes[audio];
590 if (! pipe) {
591 /* not allocated yet */
592 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */
593 if (err < 0)
594 return err;
595 chip->playback_pipes[audio] = pipe;
596 }
597 /* open for playback */
598 pipe->references++;
599
600 pipe->substream = subs;
601 tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
602 chip->playback_pipes[audio] = pipe;
603
604 runtime->hw = vx_pcm_playback_hw;
605 runtime->hw.period_bytes_min = chip->ibl.size;
606 runtime->private_data = pipe;
607
608 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */
609 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
610 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
611
612 return 0;
613}
614
615/*
616 * vx_pcm_playback_close - close callback for playback
617 */
618static int vx_pcm_playback_close(snd_pcm_substream_t *subs)
619{
620 vx_core_t *chip = snd_pcm_substream_chip(subs);
621 vx_pipe_t *pipe;
622
623 if (! subs->runtime->private_data)
624 return -EINVAL;
625
626 pipe = subs->runtime->private_data;
627
628 if (--pipe->references == 0) {
629 chip->playback_pipes[pipe->number] = NULL;
630 vx_free_pipe(chip, pipe);
631 }
632
633 return 0;
634
635}
636
637
638/*
639 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe
640 * @pipe: the pipe to notify
641 *
642 * NB: call with a certain lock.
643 */
644static int vx_notify_end_of_buffer(vx_core_t *chip, vx_pipe_t *pipe)
645{
646 int err;
647 struct vx_rmh rmh; /* use a temporary rmh here */
648
649 /* Toggle Dsp Host Interface into Message mode */
650 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
651 vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER);
652 vx_set_stream_cmd_params(&rmh, 0, pipe->number);
653 err = vx_send_msg_nolock(chip, &rmh);
654 if (err < 0)
655 return err;
656 /* Toggle Dsp Host Interface back to sound transfer mode */
657 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
658 return 0;
659}
660
661/*
662 * vx_pcm_playback_transfer_chunk - transfer a single chunk
663 * @subs: substream
664 * @pipe: the pipe to transfer
665 * @size: chunk size in bytes
666 *
667 * transfer a single buffer chunk. EOB notificaton is added after that.
668 * called from the interrupt handler, too.
669 *
670 * return 0 if ok.
671 */
672static int vx_pcm_playback_transfer_chunk(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe, int size)
673{
674 int space, err = 0;
675
676 space = vx_query_hbuffer_size(chip, pipe);
677 if (space < 0) {
678 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
679 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
680 snd_printd("error hbuffer\n");
681 return space;
682 }
683 if (space < size) {
684 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
685 snd_printd("no enough hbuffer space %d\n", space);
686 return -EIO; /* XRUN */
687 }
688
689 /* we don't need irqsave here, because this function
690 * is called from either trigger callback or irq handler
691 */
692 spin_lock(&chip->lock);
693 vx_pseudo_dma_write(chip, runtime, pipe, size);
694 err = vx_notify_end_of_buffer(chip, pipe);
695 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
696 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
697 spin_unlock(&chip->lock);
698 return err;
699}
700
701/*
702 * update the position of the given pipe.
703 * pipe->position is updated and wrapped within the buffer size.
704 * pipe->transferred is updated, too, but the size is not wrapped,
705 * so that the caller can check the total transferred size later
706 * (to call snd_pcm_period_elapsed).
707 */
708static int vx_update_pipe_position(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe)
709{
710 struct vx_rmh rmh;
711 int err, update;
712 u64 count;
713
714 vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
715 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
716 err = vx_send_msg(chip, &rmh);
717 if (err < 0)
718 return err;
719
720 count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1];
721 update = (int)(count - pipe->cur_count);
722 pipe->cur_count = count;
723 pipe->position += update;
724 if (pipe->position >= (int)runtime->buffer_size)
725 pipe->position %= runtime->buffer_size;
726 pipe->transferred += update;
727 return 0;
728}
729
730/*
731 * transfer the pending playback buffer data to DSP
732 * called from interrupt handler
733 */
734static void vx_pcm_playback_transfer(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe, int nchunks)
735{
736 int i, err;
737 snd_pcm_runtime_t *runtime = subs->runtime;
738
739 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
740 return;
741 for (i = 0; i < nchunks; i++) {
742 if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,
743 chip->ibl.size)) < 0)
744 return;
745 }
746}
747
748/*
749 * update the playback position and call snd_pcm_period_elapsed() if necessary
750 * called from interrupt handler
751 */
752static void vx_pcm_playback_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe)
753{
754 int err;
755 snd_pcm_runtime_t *runtime = subs->runtime;
756
757 if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {
758 if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0)
759 return;
760 if (pipe->transferred >= (int)runtime->period_size) {
761 pipe->transferred %= runtime->period_size;
762 snd_pcm_period_elapsed(subs);
763 }
764 }
765}
766
767/*
768 * start the stream and pipe.
769 * this function is called from tasklet, which is invoked by the trigger
770 * START callback.
771 */
772static void vx_pcm_delayed_start(unsigned long arg)
773{
774 snd_pcm_substream_t *subs = (snd_pcm_substream_t *)arg;
775 vx_core_t *chip = subs->pcm->private_data;
776 vx_pipe_t *pipe = subs->runtime->private_data;
777 int err;
778
779 /* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
780
781 if ((err = vx_start_stream(chip, pipe)) < 0) {
782 snd_printk(KERN_ERR "vx: cannot start stream\n");
783 return;
784 }
785 if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) {
786 snd_printk(KERN_ERR "vx: cannot start pipe\n");
787 return;
788 }
789 /* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/
790}
791
792/*
793 * vx_pcm_playback_trigger - trigger callback for playback
794 */
795static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
796{
797 vx_core_t *chip = snd_pcm_substream_chip(subs);
798 vx_pipe_t *pipe = subs->runtime->private_data;
799 int err;
800
801 if (chip->chip_status & VX_STAT_IS_STALE)
802 return -EBUSY;
803
804 switch (cmd) {
805 case SNDRV_PCM_TRIGGER_START:
806 case SNDRV_PCM_TRIGGER_RESUME:
807 if (! pipe->is_capture)
808 vx_pcm_playback_transfer(chip, subs, pipe, 2);
809 /* FIXME:
810 * we trigger the pipe using tasklet, so that the interrupts are
811 * issued surely after the trigger is completed.
812 */
813 tasklet_hi_schedule(&pipe->start_tq);
814 chip->pcm_running++;
815 pipe->running = 1;
816 break;
817 case SNDRV_PCM_TRIGGER_STOP:
818 case SNDRV_PCM_TRIGGER_SUSPEND:
819 vx_toggle_pipe(chip, pipe, 0);
820 vx_stop_pipe(chip, pipe);
821 vx_stop_stream(chip, pipe);
822 chip->pcm_running--;
823 pipe->running = 0;
824 break;
825 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
826 if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0)
827 return err;
828 break;
829 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
830 if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0)
831 return err;
832 break;
833 default:
834 return -EINVAL;
835 }
836 return 0;
837}
838
839/*
840 * vx_pcm_playback_pointer - pointer callback for playback
841 */
842static snd_pcm_uframes_t vx_pcm_playback_pointer(snd_pcm_substream_t *subs)
843{
844 snd_pcm_runtime_t *runtime = subs->runtime;
845 vx_pipe_t *pipe = runtime->private_data;
846 return pipe->position;
847}
848
849/*
850 * vx_pcm_hw_params - hw_params callback for playback and capture
851 */
852static int vx_pcm_hw_params(snd_pcm_substream_t *subs,
853 snd_pcm_hw_params_t *hw_params)
854{
855 return snd_pcm_alloc_vmalloc_buffer(subs, params_buffer_bytes(hw_params));
856}
857
858/*
859 * vx_pcm_hw_free - hw_free callback for playback and capture
860 */
861static int vx_pcm_hw_free(snd_pcm_substream_t *subs)
862{
863 return snd_pcm_free_vmalloc_buffer(subs);
864}
865
866/*
867 * vx_pcm_prepare - prepare callback for playback and capture
868 */
869static int vx_pcm_prepare(snd_pcm_substream_t *subs)
870{
871 vx_core_t *chip = snd_pcm_substream_chip(subs);
872 snd_pcm_runtime_t *runtime = subs->runtime;
873 vx_pipe_t *pipe = runtime->private_data;
874 int err, data_mode;
875 // int max_size, nchunks;
876
877 if (chip->chip_status & VX_STAT_IS_STALE)
878 return -EBUSY;
879
880 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
881 if (data_mode != pipe->data_mode && ! pipe->is_capture) {
882 /* IEC958 status (raw-mode) was changed */
883 /* we reopen the pipe */
884 struct vx_rmh rmh;
885 snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode);
886 vx_init_rmh(&rmh, CMD_FREE_PIPE);
887 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);
888 if ((err = vx_send_msg(chip, &rmh)) < 0)
889 return err;
890 vx_init_rmh(&rmh, CMD_RES_PIPE);
891 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);
892 if (data_mode)
893 rmh.Cmd[0] |= BIT_DATA_MODE;
894 if ((err = vx_send_msg(chip, &rmh)) < 0)
895 return err;
896 pipe->data_mode = data_mode;
897 }
898
899 if (chip->pcm_running && chip->freq != runtime->rate) {
900 snd_printk(KERN_ERR "vx: cannot set different clock %d from the current %d\n", runtime->rate, chip->freq);
901 return -EINVAL;
902 }
903 vx_set_clock(chip, runtime->rate);
904
905 if ((err = vx_set_format(chip, pipe, runtime)) < 0)
906 return err;
907
908 if (vx_is_pcmcia(chip)) {
909 pipe->align = 2; /* 16bit word */
910 } else {
911 pipe->align = 4; /* 32bit word */
912 }
913
914 pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
915 pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size);
916 pipe->hw_ptr = 0;
917
918 /* set the timestamp */
919 vx_update_pipe_position(chip, runtime, pipe);
920 /* clear again */
921 pipe->transferred = 0;
922 pipe->position = 0;
923
924 pipe->prepared = 1;
925
926 return 0;
927}
928
929
930/*
931 * operators for PCM playback
932 */
933static snd_pcm_ops_t vx_pcm_playback_ops = {
934 .open = vx_pcm_playback_open,
935 .close = vx_pcm_playback_close,
936 .ioctl = snd_pcm_lib_ioctl,
937 .hw_params = vx_pcm_hw_params,
938 .hw_free = vx_pcm_hw_free,
939 .prepare = vx_pcm_prepare,
940 .trigger = vx_pcm_trigger,
941 .pointer = vx_pcm_playback_pointer,
942 .page = snd_pcm_get_vmalloc_page,
943};
944
945
946/*
947 * playback hw information
948 */
949
950static snd_pcm_hardware_t vx_pcm_capture_hw = {
951 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
952 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID |
953 SNDRV_PCM_INFO_RESUME),
954 .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
955 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
956 .rate_min = 5000,
957 .rate_max = 48000,
958 .channels_min = 1,
959 .channels_max = 2,
960 .buffer_bytes_max = (128*1024),
961 .period_bytes_min = 126,
962 .period_bytes_max = (128*1024),
963 .periods_min = 2,
964 .periods_max = VX_MAX_PERIODS,
965 .fifo_size = 126,
966};
967
968
969/*
970 * vx_pcm_capture_open - open callback for capture
971 */
972static int vx_pcm_capture_open(snd_pcm_substream_t *subs)
973{
974 snd_pcm_runtime_t *runtime = subs->runtime;
975 vx_core_t *chip = snd_pcm_substream_chip(subs);
976 vx_pipe_t *pipe;
977 vx_pipe_t *pipe_out_monitoring = NULL;
978 unsigned int audio;
979 int err;
980
981 if (chip->chip_status & VX_STAT_IS_STALE)
982 return -EBUSY;
983
984 audio = subs->pcm->device * 2;
985 snd_assert(audio < chip->audio_ins, return -EINVAL);
986 err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);
987 if (err < 0)
988 return err;
989 pipe->substream = subs;
990 tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
991 chip->capture_pipes[audio] = pipe;
992
993 /* check if monitoring is needed */
994 if (chip->audio_monitor_active[audio]) {
995 pipe_out_monitoring = chip->playback_pipes[audio];
996 if (! pipe_out_monitoring) {
997 /* allocate a pipe */
998 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring);
999 if (err < 0)
1000 return err;
1001 chip->playback_pipes[audio] = pipe_out_monitoring;
1002 }
1003 pipe_out_monitoring->references++;
1004 /*
1005 if an output pipe is available, it's audios still may need to be
1006 unmuted. hence we'll have to call a mixer entry point.
1007 */
1008 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], chip->audio_monitor_active[audio]);
1009 /* assuming stereo */
1010 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], chip->audio_monitor_active[audio+1]);
1011 }
1012
1013 pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */
1014
1015 runtime->hw = vx_pcm_capture_hw;
1016 runtime->hw.period_bytes_min = chip->ibl.size;
1017 runtime->private_data = pipe;
1018
1019 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */
1020 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
1021 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
1022
1023 return 0;
1024}
1025
1026/*
1027 * vx_pcm_capture_close - close callback for capture
1028 */
1029static int vx_pcm_capture_close(snd_pcm_substream_t *subs)
1030{
1031 vx_core_t *chip = snd_pcm_substream_chip(subs);
1032 vx_pipe_t *pipe;
1033 vx_pipe_t *pipe_out_monitoring;
1034
1035 if (! subs->runtime->private_data)
1036 return -EINVAL;
1037 pipe = subs->runtime->private_data;
1038 chip->capture_pipes[pipe->number] = NULL;
1039
1040 pipe_out_monitoring = pipe->monitoring_pipe;
1041
1042 /*
1043 if an output pipe is attached to this input,
1044 check if it needs to be released.
1045 */
1046 if (pipe_out_monitoring) {
1047 if (--pipe_out_monitoring->references == 0) {
1048 vx_free_pipe(chip, pipe_out_monitoring);
1049 chip->playback_pipes[pipe->number] = NULL;
1050 pipe->monitoring_pipe = NULL;
1051 }
1052 }
1053
1054 vx_free_pipe(chip, pipe);
1055 return 0;
1056}
1057
1058
1059
1060#define DMA_READ_ALIGN 6 /* hardware alignment for read */
1061
1062/*
1063 * vx_pcm_capture_update - update the capture buffer
1064 */
1065static void vx_pcm_capture_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe)
1066{
1067 int size, space, count;
1068 snd_pcm_runtime_t *runtime = subs->runtime;
1069
1070 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
1071 return;
1072
1073 size = runtime->buffer_size - snd_pcm_capture_avail(runtime);
1074 if (! size)
1075 return;
1076 size = frames_to_bytes(runtime, size);
1077 space = vx_query_hbuffer_size(chip, pipe);
1078 if (space < 0)
1079 goto _error;
1080 if (size > space)
1081 size = space;
1082 size = (size / 3) * 3; /* align to 3 bytes */
1083 if (size < DMA_READ_ALIGN)
1084 goto _error;
1085
1086 /* keep the last 6 bytes, they will be read after disconnection */
1087 count = size - DMA_READ_ALIGN;
1088 /* read bytes until the current pointer reaches to the aligned position
1089 * for word-transfer
1090 */
1091 while (count > 0) {
1092 if ((pipe->hw_ptr % pipe->align) == 0)
1093 break;
1094 if (vx_wait_for_rx_full(chip) < 0)
1095 goto _error;
1096 vx_pcm_read_per_bytes(chip, runtime, pipe);
1097 count -= 3;
1098 }
1099 if (count > 0) {
1100 /* ok, let's accelerate! */
1101 int align = pipe->align * 3;
1102 space = (count / align) * align;
1103 vx_pseudo_dma_read(chip, runtime, pipe, space);
1104 count -= space;
1105 }
1106 /* read the rest of bytes */
1107 while (count > 0) {
1108 if (vx_wait_for_rx_full(chip) < 0)
1109 goto _error;
1110 vx_pcm_read_per_bytes(chip, runtime, pipe);
1111 count -= 3;
1112 }
1113 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
1114 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
1115 /* read the last pending 6 bytes */
1116 count = DMA_READ_ALIGN;
1117 while (count > 0) {
1118 vx_pcm_read_per_bytes(chip, runtime, pipe);
1119 count -= 3;
1120 }
1121 /* update the position */
1122 pipe->transferred += size;
1123 if (pipe->transferred >= pipe->period_bytes) {
1124 pipe->transferred %= pipe->period_bytes;
1125 snd_pcm_period_elapsed(subs);
1126 }
1127 return;
1128
1129 _error:
1130 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
1131 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
1132 return;
1133}
1134
1135/*
1136 * vx_pcm_capture_pointer - pointer callback for capture
1137 */
1138static snd_pcm_uframes_t vx_pcm_capture_pointer(snd_pcm_substream_t *subs)
1139{
1140 snd_pcm_runtime_t *runtime = subs->runtime;
1141 vx_pipe_t *pipe = runtime->private_data;
1142 return bytes_to_frames(runtime, pipe->hw_ptr);
1143}
1144
1145/*
1146 * operators for PCM capture
1147 */
1148static snd_pcm_ops_t vx_pcm_capture_ops = {
1149 .open = vx_pcm_capture_open,
1150 .close = vx_pcm_capture_close,
1151 .ioctl = snd_pcm_lib_ioctl,
1152 .hw_params = vx_pcm_hw_params,
1153 .hw_free = vx_pcm_hw_free,
1154 .prepare = vx_pcm_prepare,
1155 .trigger = vx_pcm_trigger,
1156 .pointer = vx_pcm_capture_pointer,
1157 .page = snd_pcm_get_vmalloc_page,
1158};
1159
1160
1161/*
1162 * interrupt handler for pcm streams
1163 */
1164void vx_pcm_update_intr(vx_core_t *chip, unsigned int events)
1165{
1166 unsigned int i;
1167 vx_pipe_t *pipe;
1168
1169#define EVENT_MASK (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)
1170
1171 if (events & EVENT_MASK) {
1172 vx_init_rmh(&chip->irq_rmh, CMD_ASYNC);
1173 if (events & ASYNC_EVENTS_PENDING)
1174 chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */
1175 if (events & END_OF_BUFFER_EVENTS_PENDING)
1176 chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */
1177
1178 if (vx_send_msg(chip, &chip->irq_rmh) < 0) {
1179 snd_printdd(KERN_ERR "msg send error!!\n");
1180 return;
1181 }
1182
1183 i = 1;
1184 while (i < chip->irq_rmh.LgStat) {
1185 int p, buf, capture, eob;
1186 p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD;
1187 capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0;
1188 eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0;
1189 i++;
1190 if (events & ASYNC_EVENTS_PENDING)
1191 i++;
1192 buf = 1; /* force to transfer */
1193 if (events & END_OF_BUFFER_EVENTS_PENDING) {
1194 if (eob)
1195 buf = chip->irq_rmh.Stat[i];
1196 i++;
1197 }
1198 if (capture)
1199 continue;
1200 snd_assert(p >= 0 && (unsigned int)p < chip->audio_outs,);
1201 pipe = chip->playback_pipes[p];
1202 if (pipe && pipe->substream) {
1203 vx_pcm_playback_update(chip, pipe->substream, pipe);
1204 vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf);
1205 }
1206 }
1207 }
1208
1209 /* update the capture pcm pointers as frequently as possible */
1210 for (i = 0; i < chip->audio_ins; i++) {
1211 pipe = chip->capture_pipes[i];
1212 if (pipe && pipe->substream)
1213 vx_pcm_capture_update(chip, pipe->substream, pipe);
1214 }
1215}
1216
1217
1218/*
1219 * vx_init_audio_io - check the availabe audio i/o and allocate pipe arrays
1220 */
1221static int vx_init_audio_io(vx_core_t *chip)
1222{
1223 struct vx_rmh rmh;
1224 int preferred;
1225
1226 vx_init_rmh(&rmh, CMD_SUPPORTED);
1227 if (vx_send_msg(chip, &rmh) < 0) {
1228 snd_printk(KERN_ERR "vx: cannot get the supported audio data\n");
1229 return -ENXIO;
1230 }
1231
1232 chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD;
1233 chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD;
1234 chip->audio_info = rmh.Stat[1];
1235
1236 /* allocate pipes */
1237 chip->playback_pipes = kmalloc(sizeof(vx_pipe_t *) * chip->audio_outs, GFP_KERNEL);
1238 chip->capture_pipes = kmalloc(sizeof(vx_pipe_t *) * chip->audio_ins, GFP_KERNEL);
1239 if (! chip->playback_pipes || ! chip->capture_pipes)
1240 return -ENOMEM;
1241
1242 memset(chip->playback_pipes, 0, sizeof(vx_pipe_t *) * chip->audio_outs);
1243 memset(chip->capture_pipes, 0, sizeof(vx_pipe_t *) * chip->audio_ins);
1244
1245 preferred = chip->ibl.size;
1246 chip->ibl.size = 0;
1247 vx_set_ibl(chip, &chip->ibl); /* query the info */
1248 if (preferred > 0) {
1249 chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / chip->ibl.granularity) * chip->ibl.granularity;
1250 if (chip->ibl.size > chip->ibl.max_size)
1251 chip->ibl.size = chip->ibl.max_size;
1252 } else
1253 chip->ibl.size = chip->ibl.min_size; /* set to the minimum */
1254 vx_set_ibl(chip, &chip->ibl);
1255
1256 return 0;
1257}
1258
1259
1260/*
1261 * free callback for pcm
1262 */
1263static void snd_vx_pcm_free(snd_pcm_t *pcm)
1264{
1265 vx_core_t *chip = pcm->private_data;
1266 chip->pcm[pcm->device] = NULL;
1267 if (chip->playback_pipes) {
1268 kfree(chip->playback_pipes);
1269 chip->playback_pipes = NULL;
1270 }
1271 if (chip->capture_pipes) {
1272 kfree(chip->capture_pipes);
1273 chip->capture_pipes = NULL;
1274 }
1275}
1276
1277/*
1278 * snd_vx_pcm_new - create and initialize a pcm
1279 */
1280int snd_vx_pcm_new(vx_core_t *chip)
1281{
1282 snd_pcm_t *pcm;
1283 unsigned int i;
1284 int err;
1285
1286 if ((err = vx_init_audio_io(chip)) < 0)
1287 return err;
1288
1289 for (i = 0; i < chip->hw->num_codecs; i++) {
1290 unsigned int outs, ins;
1291 outs = chip->audio_outs > i * 2 ? 1 : 0;
1292 ins = chip->audio_ins > i * 2 ? 1 : 0;
1293 if (! outs && ! ins)
1294 break;
1295 err = snd_pcm_new(chip->card, "VX PCM", i,
1296 outs, ins, &pcm);
1297 if (err < 0)
1298 return err;
1299 if (outs)
1300 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);
1301 if (ins)
1302 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);
1303
1304 pcm->private_data = chip;
1305 pcm->private_free = snd_vx_pcm_free;
1306 pcm->info_flags = 0;
1307 strcpy(pcm->name, chip->card->shortname);
1308 chip->pcm[i] = pcm;
1309 }
1310
1311 return 0;
1312}
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
new file mode 100644
index 000000000000..18114713c3b3
--- /dev/null
+++ b/sound/drivers/vx/vx_uer.c
@@ -0,0 +1,321 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * IEC958 stuff
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/delay.h>
25#include <sound/core.h>
26#include <sound/vx_core.h>
27#include "vx_cmd.h"
28
29
30/*
31 * vx_modify_board_clock - tell the board that its clock has been modified
32 * @sync: DSP needs to resynchronize its FIFO
33 */
34static int vx_modify_board_clock(vx_core_t *chip, int sync)
35{
36 struct vx_rmh rmh;
37
38 vx_init_rmh(&rmh, CMD_MODIFY_CLOCK);
39 /* Ask the DSP to resynchronize its FIFO. */
40 if (sync)
41 rmh.Cmd[0] |= CMD_MODIFY_CLOCK_S_BIT;
42 return vx_send_msg(chip, &rmh);
43}
44
45/*
46 * vx_modify_board_inputs - resync audio inputs
47 */
48static int vx_modify_board_inputs(vx_core_t *chip)
49{
50 struct vx_rmh rmh;
51
52 vx_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
53 rmh.Cmd[0] |= 1 << 0; /* reference: AUDIO 0 */
54 return vx_send_msg(chip, &rmh);
55}
56
57/*
58 * vx_read_one_cbit - read one bit from UER config
59 * @index: the bit index
60 * returns 0 or 1.
61 */
62static int vx_read_one_cbit(vx_core_t *chip, int index)
63{
64 unsigned long flags;
65 int val;
66 spin_lock_irqsave(&chip->lock, flags);
67 if (chip->type >= VX_TYPE_VXPOCKET) {
68 vx_outb(chip, CSUER, 1); /* read */
69 vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
70 val = (vx_inb(chip, RUER) >> 7) & 0x01;
71 } else {
72 vx_outl(chip, CSUER, 1); /* read */
73 vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
74 val = (vx_inl(chip, RUER) >> 7) & 0x01;
75 }
76 spin_unlock_irqrestore(&chip->lock, flags);
77 return val;
78}
79
80/*
81 * vx_write_one_cbit - write one bit to UER config
82 * @index: the bit index
83 * @val: bit value, 0 or 1
84 */
85static void vx_write_one_cbit(vx_core_t *chip, int index, int val)
86{
87 unsigned long flags;
88 val = !!val; /* 0 or 1 */
89 spin_lock_irqsave(&chip->lock, flags);
90 if (vx_is_pcmcia(chip)) {
91 vx_outb(chip, CSUER, 0); /* write */
92 vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
93 } else {
94 vx_outl(chip, CSUER, 0); /* write */
95 vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
96 }
97 spin_unlock_irqrestore(&chip->lock, flags);
98}
99
100/*
101 * vx_read_uer_status - read the current UER status
102 * @mode: pointer to store the UER mode, VX_UER_MODE_XXX
103 *
104 * returns the frequency of UER, or 0 if not sync,
105 * or a negative error code.
106 */
107static int vx_read_uer_status(vx_core_t *chip, int *mode)
108{
109 int val, freq;
110
111 /* Default values */
112 freq = 0;
113
114 /* Read UER status */
115 if (vx_is_pcmcia(chip))
116 val = vx_inb(chip, CSUER);
117 else
118 val = vx_inl(chip, CSUER);
119 if (val < 0)
120 return val;
121 /* If clock is present, read frequency */
122 if (val & VX_SUER_CLOCK_PRESENT_MASK) {
123 switch (val & VX_SUER_FREQ_MASK) {
124 case VX_SUER_FREQ_32KHz_MASK:
125 freq = 32000;
126 break;
127 case VX_SUER_FREQ_44KHz_MASK:
128 freq = 44100;
129 break;
130 case VX_SUER_FREQ_48KHz_MASK:
131 freq = 48000;
132 break;
133 }
134 }
135 if (val & VX_SUER_DATA_PRESENT_MASK)
136 /* bit 0 corresponds to consumer/professional bit */
137 *mode = vx_read_one_cbit(chip, 0) ?
138 VX_UER_MODE_PROFESSIONAL : VX_UER_MODE_CONSUMER;
139 else
140 *mode = VX_UER_MODE_NOT_PRESENT;
141
142 return freq;
143}
144
145
146/*
147 * compute the sample clock value from frequency
148 *
149 * The formula is as follows:
150 *
151 * HexFreq = (dword) ((double) ((double) 28224000 / (double) Frequency))
152 * switch ( HexFreq & 0x00000F00 )
153 * case 0x00000100: ;
154 * case 0x00000200:
155 * case 0x00000300: HexFreq -= 0x00000201 ;
156 * case 0x00000400:
157 * case 0x00000500:
158 * case 0x00000600:
159 * case 0x00000700: HexFreq = (dword) (((double) 28224000 / (double) (Frequency*2)) - 1)
160 * default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF
161 */
162
163static int vx_calc_clock_from_freq(vx_core_t *chip, int freq)
164{
165#define XX_FECH48000 0x0000004B
166#define XX_FECH32000 0x00000171
167#define XX_FECH24000 0x0000024B
168#define XX_FECH16000 0x00000371
169#define XX_FECH12000 0x0000044B
170#define XX_FECH8000 0x00000571
171#define XX_FECH44100 0x0000007F
172#define XX_FECH29400 0x0000016F
173#define XX_FECH22050 0x0000027F
174#define XX_FECH14000 0x000003EF
175#define XX_FECH11025 0x0000047F
176#define XX_FECH7350 0x000005BF
177
178 switch (freq) {
179 case 48000: return XX_FECH48000;
180 case 44100: return XX_FECH44100;
181 case 32000: return XX_FECH32000;
182 case 29400: return XX_FECH29400;
183 case 24000: return XX_FECH24000;
184 case 22050: return XX_FECH22050;
185 case 16000: return XX_FECH16000;
186 case 14000: return XX_FECH14000;
187 case 12000: return XX_FECH12000;
188 case 11025: return XX_FECH11025;
189 case 8000: return XX_FECH8000;
190 case 7350: return XX_FECH7350;
191 default: return freq; /* The value is already correct */
192 }
193}
194
195
196/*
197 * vx_change_clock_source - change the clock source
198 * @source: the new source
199 */
200static void vx_change_clock_source(vx_core_t *chip, int source)
201{
202 unsigned long flags;
203
204 /* we mute DAC to prevent clicks */
205 vx_toggle_dac_mute(chip, 1);
206 spin_lock_irqsave(&chip->lock, flags);
207 chip->ops->set_clock_source(chip, source);
208 chip->clock_source = source;
209 spin_unlock_irqrestore(&chip->lock, flags);
210 /* unmute */
211 vx_toggle_dac_mute(chip, 0);
212}
213
214
215/*
216 * set the internal clock
217 */
218void vx_set_internal_clock(vx_core_t *chip, unsigned int freq)
219{
220 int clock;
221 unsigned long flags;
222 /* Get real clock value */
223 clock = vx_calc_clock_from_freq(chip, freq);
224 snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq);
225 spin_lock_irqsave(&chip->lock, flags);
226 if (vx_is_pcmcia(chip)) {
227 vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
228 vx_outb(chip, LOFREQ, clock & 0xff);
229 } else {
230 vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f);
231 vx_outl(chip, LOFREQ, clock & 0xff);
232 }
233 spin_unlock_irqrestore(&chip->lock, flags);
234}
235
236
237/*
238 * set the iec958 status bits
239 * @bits: 32-bit status bits
240 */
241void vx_set_iec958_status(vx_core_t *chip, unsigned int bits)
242{
243 int i;
244
245 if (chip->chip_status & VX_STAT_IS_STALE)
246 return;
247
248 for (i = 0; i < 32; i++)
249 vx_write_one_cbit(chip, i, bits & (1 << i));
250}
251
252
253/*
254 * vx_set_clock - change the clock and audio source if necessary
255 */
256int vx_set_clock(vx_core_t *chip, unsigned int freq)
257{
258 int src_changed = 0;
259
260 if (chip->chip_status & VX_STAT_IS_STALE)
261 return 0;
262
263 /* change the audio source if possible */
264 vx_sync_audio_source(chip);
265
266 if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL ||
267 (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
268 chip->audio_source == VX_AUDIO_SRC_DIGITAL)) {
269 if (chip->clock_source != UER_SYNC) {
270 vx_change_clock_source(chip, UER_SYNC);
271 mdelay(6);
272 src_changed = 1;
273 }
274 } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL ||
275 (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
276 chip->audio_source != VX_AUDIO_SRC_DIGITAL)) {
277 if (chip->clock_source != INTERNAL_QUARTZ) {
278 vx_change_clock_source(chip, INTERNAL_QUARTZ);
279 src_changed = 1;
280 }
281 if (chip->freq == freq)
282 return 0;
283 vx_set_internal_clock(chip, freq);
284 if (src_changed)
285 vx_modify_board_inputs(chip);
286 }
287 if (chip->freq == freq)
288 return 0;
289 chip->freq = freq;
290 vx_modify_board_clock(chip, 1);
291 return 0;
292}
293
294
295/*
296 * vx_change_frequency - called from interrupt handler
297 */
298int vx_change_frequency(vx_core_t *chip)
299{
300 int freq;
301
302 if (chip->chip_status & VX_STAT_IS_STALE)
303 return 0;
304
305 if (chip->clock_source == INTERNAL_QUARTZ)
306 return 0;
307 /*
308 * Read the real UER board frequency
309 */
310 freq = vx_read_uer_status(chip, &chip->uer_detected);
311 if (freq < 0)
312 return freq;
313 /*
314 * The frequency computed by the DSP is good and
315 * is different from the previous computed.
316 */
317 if (freq == 48000 || freq == 44100 || freq == 32000)
318 chip->freq_detected = freq;
319
320 return 0;
321}