This source file includes following definitions.
- scale_vol
- write_mix
- set_volumes
- ics2101_mixer_ioctl
- ics2101_mixer_init
1
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 #include "sound_config.h"
31 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
32
33 #include <linux/ultrasound.h>
34 #include "gus_hw.h"
35
36 #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
37 SOUND_MASK_SYNTH| \
38 SOUND_MASK_CD | SOUND_MASK_VOLUME)
39
40 extern int gus_base;
41 static int volumes[ICS_MIXDEVS];
42 static int left_fix[ICS_MIXDEVS] =
43 {1, 1, 1, 2, 1, 2};
44 static int right_fix[ICS_MIXDEVS] =
45 {2, 2, 2, 1, 2, 1};
46
47 static int
48 scale_vol (int vol)
49 {
50 #if 1
51
52
53
54
55
56 int e;
57
58 if (vol < 0)
59 vol = 0;
60 if (vol > 100)
61 vol = 100;
62 vol = (31 * vol + 50) / 100;
63 e = 0;
64 if (vol)
65 {
66 while (vol < 16)
67 {
68 vol <<= 1;
69 e--;
70 }
71 vol -= 16;
72 e += 7;
73 }
74 return ((e << 4) + vol);
75 #else
76 return ((vol * 127) + 50) / 100;
77 #endif
78 }
79
80 static void
81 write_mix (int dev, int chn, int vol)
82 {
83 int *selector;
84 unsigned long flags;
85 int ctrl_addr = dev << 3;
86 int attn_addr = dev << 3;
87
88 vol = scale_vol (vol);
89
90 if (chn == CHN_LEFT)
91 {
92 selector = left_fix;
93 ctrl_addr |= 0x00;
94 attn_addr |= 0x02;
95 }
96 else
97 {
98 selector = right_fix;
99 ctrl_addr |= 0x01;
100 attn_addr |= 0x03;
101 }
102
103 DISABLE_INTR (flags);
104 OUTB (ctrl_addr, u_MixSelect);
105 OUTB (selector[dev], u_MixData);
106 OUTB (attn_addr, u_MixSelect);
107 OUTB ((unsigned char) vol, u_MixData);
108 RESTORE_INTR (flags);
109 }
110
111 static int
112 set_volumes (int dev, int vol)
113 {
114 int left = vol & 0x00ff;
115 int right = (vol >> 8) & 0x00ff;
116
117 if (left < 0)
118 left = 0;
119 if (left > 100)
120 left = 100;
121 if (right < 0)
122 right = 0;
123 if (right > 100)
124 right = 100;
125
126 write_mix (dev, CHN_LEFT, left);
127 write_mix (dev, CHN_RIGHT, right);
128
129 vol = left + (right << 8);
130 volumes[dev] = vol;
131 return vol;
132 }
133
134 static int
135 ics2101_mixer_ioctl (int dev, unsigned int cmd, unsigned int arg)
136 {
137 if (((cmd >> 8) & 0xff) == 'M')
138 {
139 if (cmd & IOC_IN)
140 switch (cmd & 0xff)
141 {
142 case SOUND_MIXER_RECSRC:
143 return gus_default_mixer_ioctl (dev, cmd, arg);
144 break;
145
146 case SOUND_MIXER_MIC:
147 return IOCTL_OUT (arg, set_volumes (DEV_MIC, IOCTL_IN (arg)));
148 break;
149
150 case SOUND_MIXER_CD:
151 return IOCTL_OUT (arg, set_volumes (DEV_CD, IOCTL_IN (arg)));
152 break;
153
154 case SOUND_MIXER_LINE:
155 return IOCTL_OUT (arg, set_volumes (DEV_LINE, IOCTL_IN (arg)));
156 break;
157
158 case SOUND_MIXER_SYNTH:
159 return IOCTL_OUT (arg, set_volumes (DEV_GF1, IOCTL_IN (arg)));
160 break;
161
162 case SOUND_MIXER_VOLUME:
163 return IOCTL_OUT (arg, set_volumes (DEV_VOL, IOCTL_IN (arg)));
164 break;
165
166 default:
167 return RET_ERROR (EINVAL);
168 }
169 else
170 switch (cmd & 0xff)
171
172
173 {
174
175 case SOUND_MIXER_RECSRC:
176 return gus_default_mixer_ioctl (dev, cmd, arg);
177 break;
178
179 case SOUND_MIXER_DEVMASK:
180 return IOCTL_OUT (arg, MIX_DEVS);
181 break;
182
183 case SOUND_MIXER_STEREODEVS:
184 return IOCTL_OUT (arg, SOUND_MASK_LINE | SOUND_MASK_CD |
185 SOUND_MASK_SYNTH | SOUND_MASK_VOLUME |
186 SOUND_MASK_MIC);
187 break;
188
189 case SOUND_MIXER_RECMASK:
190 return IOCTL_OUT (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
191 break;
192
193 case SOUND_MIXER_CAPS:
194 return IOCTL_OUT (arg, 0);
195 break;
196
197 case SOUND_MIXER_MIC:
198 return IOCTL_OUT (arg, volumes[DEV_MIC]);
199 break;
200
201 case SOUND_MIXER_LINE:
202 return IOCTL_OUT (arg, volumes[DEV_LINE]);
203 break;
204
205 case SOUND_MIXER_CD:
206 return IOCTL_OUT (arg, volumes[DEV_CD]);
207 break;
208
209 case SOUND_MIXER_VOLUME:
210 return IOCTL_OUT (arg, volumes[DEV_VOL]);
211 break;
212
213 case SOUND_MIXER_SYNTH:
214 return IOCTL_OUT (arg, volumes[DEV_GF1]);
215 break;
216
217 default:
218 return RET_ERROR (EINVAL);
219 }
220 }
221
222 return RET_ERROR (EINVAL);
223 }
224
225 static struct mixer_operations ics2101_mixer_operations =
226 {
227 ics2101_mixer_ioctl
228 };
229
230 long
231 ics2101_mixer_init (long mem_start)
232 {
233 int i;
234
235 if (num_mixers < MAX_MIXER_DEV)
236 {
237 mixer_devs[num_mixers++] = &ics2101_mixer_operations;
238
239
240
241
242
243
244 if (INB (u_MixSelect) != 5)
245 {
246 for (i = 0; i < ICS_MIXDEVS; i++)
247 left_fix[i] = 1;
248 for (i = 0; i < ICS_MIXDEVS; i++)
249 right_fix[i] = 2;
250 }
251
252 set_volumes (DEV_GF1, 0x5a5a);
253 set_volumes (DEV_CD, 0x5a5a);
254 set_volumes (DEV_MIC, 0x0000);
255 set_volumes (DEV_LINE, 0x5a5a);
256 set_volumes (DEV_VOL, 0x5a5a);
257 set_volumes (DEV_UNUSED, 0x0000);
258 }
259
260 return mem_start;
261 }
262
263 #endif