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