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