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 #include <linux/config.h>
30
31
32 #include "sound_config.h"
33 #if defined(CONFIG_GUS)
34
35 #include <linux/ultrasound.h>
36 #include "gus_hw.h"
37
38 #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
39 SOUND_MASK_SYNTH| \
40 SOUND_MASK_CD | SOUND_MASK_VOLUME)
41
42 extern int *gus_osp;
43 extern int gus_base;
44 static int volumes[ICS_MIXDEVS];
45 static int left_fix[ICS_MIXDEVS] =
46 {1, 1, 1, 2, 1, 2};
47 static int right_fix[ICS_MIXDEVS] =
48 {2, 2, 2, 1, 2, 1};
49
50 static int
51 scale_vol (int vol)
52 {
53
54
55
56
57
58 int e;
59
60 if (vol < 0)
61 vol = 0;
62 if (vol > 100)
63 vol = 100;
64 vol = (31 * vol + 50) / 100;
65 e = 0;
66 if (vol)
67 {
68 while (vol < 16)
69 {
70 vol <<= 1;
71 e--;
72 }
73 vol -= 16;
74 e += 7;
75 }
76 return ((e << 4) + vol);
77 }
78
79 static void
80 write_mix (int dev, int chn, int vol)
81 {
82 int *selector;
83 unsigned long flags;
84 int ctrl_addr = dev << 3;
85 int attn_addr = dev << 3;
86
87 vol = scale_vol (vol);
88
89 if (chn == CHN_LEFT)
90 {
91 selector = left_fix;
92 ctrl_addr |= 0x00;
93 attn_addr |= 0x02;
94 }
95 else
96 {
97 selector = right_fix;
98 ctrl_addr |= 0x01;
99 attn_addr |= 0x03;
100 }
101
102 save_flags (flags);
103 cli ();
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_flags (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, caddr_t arg)
136 {
137 if (((cmd >> 8) & 0xff) == 'M')
138 {
139 if (_IOC_DIR (cmd) & _IOC_WRITE)
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 snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_fs_long ((long *) arg)));
148 break;
149
150 case SOUND_MIXER_CD:
151 return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_fs_long ((long *) arg)));
152 break;
153
154 case SOUND_MIXER_LINE:
155 return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_fs_long ((long *) arg)));
156 break;
157
158 case SOUND_MIXER_SYNTH:
159 return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_fs_long ((long *) arg)));
160 break;
161
162 case SOUND_MIXER_VOLUME:
163 return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_fs_long ((long *) arg)));
164 break;
165
166 default:
167 return -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 snd_ioctl_return ((int *) arg, MIX_DEVS);
181 break;
182
183 case SOUND_MIXER_STEREODEVS:
184 return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
185 break;
186
187 case SOUND_MIXER_RECMASK:
188 return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
189 break;
190
191 case SOUND_MIXER_CAPS:
192 return snd_ioctl_return ((int *) arg, 0);
193 break;
194
195 case SOUND_MIXER_MIC:
196 return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]);
197 break;
198
199 case SOUND_MIXER_LINE:
200 return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]);
201 break;
202
203 case SOUND_MIXER_CD:
204 return snd_ioctl_return ((int *) arg, volumes[DEV_CD]);
205 break;
206
207 case SOUND_MIXER_VOLUME:
208 return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]);
209 break;
210
211 case SOUND_MIXER_SYNTH:
212 return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]);
213 break;
214
215 default:
216 return -EINVAL;
217 }
218 }
219
220 return -EINVAL;
221 }
222
223 static struct mixer_operations ics2101_mixer_operations =
224 {
225 "ICS2101 Multimedia Mixer",
226 ics2101_mixer_ioctl
227 };
228
229 long
230 ics2101_mixer_init (long mem_start)
231 {
232 int i;
233
234 if (num_mixers < MAX_MIXER_DEV)
235 {
236 mixer_devs[num_mixers++] = &ics2101_mixer_operations;
237
238
239
240
241
242
243 if (inb (u_MixSelect) != 5)
244 {
245 for (i = 0; i < ICS_MIXDEVS; i++)
246 left_fix[i] = 1;
247 for (i = 0; i < ICS_MIXDEVS; i++)
248 right_fix[i] = 2;
249 }
250
251 set_volumes (DEV_GF1, 0x5a5a);
252 set_volumes (DEV_CD, 0x5a5a);
253 set_volumes (DEV_MIC, 0x0000);
254 set_volumes (DEV_LINE, 0x5a5a);
255 set_volumes (DEV_VOL, 0x5a5a);
256 set_volumes (DEV_UNUSED, 0x0000);
257 }
258
259 return mem_start;
260 }
261
262 #endif