This source file includes following definitions.
- mix_write
- mixer_output
- set_mode
- pas_mixer_set
- pas_mixer_reset
- pas_mixer_ioctl
- pas_init_mixer
1 #define _PAS2_MIXER_C_
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include "sound_config.h"
33
34 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS)
35
36 #include "pas.h"
37
38 #define TRACE(what)
39
40 extern int translat_code;
41 extern char pas_model;
42 extern sound_os_info *pas_osp;
43
44 static int rec_devices = (SOUND_MASK_MIC);
45 static int mode_control = 0;
46
47 #define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
48 SOUND_MASK_CD | SOUND_MASK_ALTPCM)
49
50 #define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
51 SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \
52 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV | \
53 SOUND_MASK_MUTE | SOUND_MASK_ENHANCE | SOUND_MASK_LOUD)
54
55 static unsigned short levels[SOUND_MIXER_NRDEVICES] =
56 {
57 0x3232,
58 0x3232,
59 0x3232,
60 0x5050,
61 0x4b4b,
62 0x3232,
63 0x4b4b,
64 0x4b4b,
65 0x4b4b,
66 0x6464,
67 0x4b4b,
68 0x6464
69 };
70
71 void
72 mix_write (unsigned char data, int ioaddr)
73 {
74
75
76
77
78
79
80
81
82 if (pas_model == PAS_16D)
83 {
84 outw (data | (data << 8), (ioaddr ^ translat_code) - 1);
85 outb (0x80, 0);
86 }
87 else
88 pas_write (data, ioaddr);
89 }
90
91 static int
92 mixer_output (int right_vol, int left_vol, int div, int bits,
93 int mixer)
94 {
95 int left = left_vol * div / 100;
96 int right = right_vol * div / 100;
97
98
99 if (bits & P_M_MV508_MIXER)
100 {
101
102
103 left |= mixer;
104 right |= mixer;
105 }
106
107 if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE)
108 {
109
110
111 mix_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER);
112 mix_write (left, PARALLEL_MIXER);
113 right_vol = left_vol;
114 }
115 else
116 {
117 mix_write (P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER);
118 mix_write (left, PARALLEL_MIXER);
119 mix_write (P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER);
120 mix_write (right, PARALLEL_MIXER);
121 }
122
123 return (left_vol | (right_vol << 8));
124 }
125
126 void
127 set_mode (int new_mode)
128 {
129 mix_write (P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER);
130 mix_write (new_mode, PARALLEL_MIXER);
131
132 mode_control = new_mode;
133 }
134
135 static int
136 pas_mixer_set (int whichDev, unsigned int level)
137 {
138 int left, right, devmask, changed, i, mixer = 0;
139
140 TRACE (printk ("static int pas_mixer_set(int whichDev = %d, unsigned int level = %X)\n", whichDev, level));
141
142 left = level & 0x7f;
143 right = (level & 0x7f00) >> 8;
144
145 if (whichDev < SOUND_MIXER_NRDEVICES)
146 if ((1 << whichDev) & rec_devices)
147 mixer = P_M_MV508_INPUTMIX;
148 else
149 mixer = P_M_MV508_OUTPUTMIX;
150
151 switch (whichDev)
152 {
153 case SOUND_MIXER_VOLUME:
154 levels[whichDev] = mixer_output (right, left, 63, P_M_MV508_MASTER_A, 0);
155 break;
156
157
158
159
160
161 case SOUND_MIXER_BASS:
162 levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_BASS, 0);
163 break;
164 case SOUND_MIXER_TREBLE:
165 levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_TREBLE, 0);
166 break;
167
168 case SOUND_MIXER_SYNTH:
169 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer);
170 break;
171 case SOUND_MIXER_PCM:
172 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer);
173 break;
174 case SOUND_MIXER_ALTPCM:
175 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer);
176 break;
177 case SOUND_MIXER_SPEAKER:
178 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer);
179 break;
180 case SOUND_MIXER_LINE:
181 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer);
182 break;
183 case SOUND_MIXER_CD:
184 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer);
185 break;
186 case SOUND_MIXER_MIC:
187 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer);
188 break;
189 case SOUND_MIXER_IMIX:
190 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER,
191 P_M_MV508_OUTPUTMIX);
192 break;
193 case SOUND_MIXER_RECLEV:
194 levels[whichDev] = mixer_output (right, left, 15, P_M_MV508_MASTER_B, 0);
195 break;
196
197 case SOUND_MIXER_MUTE:
198 return 0;
199 break;
200
201 case SOUND_MIXER_ENHANCE:
202 i = 0;
203 level &= 0x7f;
204 if (level)
205 i = (level / 20) - 1;
206
207 mode_control &= ~P_M_MV508_ENHANCE_BITS;
208 mode_control |= P_M_MV508_ENHANCE_BITS;
209 set_mode (mode_control);
210
211 if (i)
212 i = (i + 1) * 20;
213 return i;
214 break;
215
216 case SOUND_MIXER_LOUD:
217 mode_control &= ~P_M_MV508_LOUDNESS;
218 if (level)
219 mode_control |= P_M_MV508_LOUDNESS;
220 set_mode (mode_control);
221 return !!level;
222 break;
223
224 case SOUND_MIXER_RECSRC:
225 devmask = level & POSSIBLE_RECORDING_DEVICES;
226
227 changed = devmask ^ rec_devices;
228 rec_devices = devmask;
229
230 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
231 if (changed & (1 << i))
232 {
233 pas_mixer_set (i, levels[i]);
234 }
235 return rec_devices;
236 break;
237
238 default:
239 return -EINVAL;
240 }
241
242 return (levels[whichDev]);
243 }
244
245
246
247 static void
248 pas_mixer_reset (void)
249 {
250 int foo;
251
252 TRACE (printk ("pas2_mixer.c: void pas_mixer_reset(void)\n"));
253
254 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
255 pas_mixer_set (foo, levels[foo]);
256
257 set_mode (P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_40);
258 }
259
260 int
261 pas_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
262 {
263 TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
264
265 if (((cmd >> 8) & 0xff) == 'M')
266 {
267 if (cmd & IOC_IN)
268 return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_fs_long ((long *) arg)));
269 else
270 {
271
272
273
274 switch (cmd & 0xff)
275 {
276
277 case SOUND_MIXER_RECSRC:
278 return snd_ioctl_return ((int *) arg, rec_devices);
279 break;
280
281 case SOUND_MIXER_STEREODEVS:
282 return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
283 break;
284
285 case SOUND_MIXER_DEVMASK:
286 return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES);
287 break;
288
289 case SOUND_MIXER_RECMASK:
290 return snd_ioctl_return ((int *) arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
291 break;
292
293 case SOUND_MIXER_CAPS:
294 return snd_ioctl_return ((int *) arg, 0);
295 break;
296
297 case SOUND_MIXER_MUTE:
298 return snd_ioctl_return ((int *) arg, 0);
299 break;
300
301 case SOUND_MIXER_ENHANCE:
302 if (!(mode_control & P_M_MV508_ENHANCE_BITS))
303 return snd_ioctl_return ((int *) arg, 0);
304 return snd_ioctl_return ((int *) arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20);
305 break;
306
307 case SOUND_MIXER_LOUD:
308 if (mode_control & P_M_MV508_LOUDNESS)
309 return snd_ioctl_return ((int *) arg, 1);
310 return snd_ioctl_return ((int *) arg, 0);
311 break;
312
313 default:
314 return snd_ioctl_return ((int *) arg, levels[cmd & 0xff]);
315 }
316 }
317 }
318 return -EINVAL;
319 }
320
321 static struct mixer_operations pas_mixer_operations =
322 {
323 "Pro Audio Spectrum 16",
324 pas_mixer_ioctl
325 };
326
327 int
328 pas_init_mixer (void)
329 {
330 pas_mixer_reset ();
331
332 if (num_mixers < MAX_MIXER_DEV)
333 mixer_devs[num_mixers++] = &pas_mixer_operations;
334 return 1;
335 }
336
337 #endif