6 FORWARD
_PROTOTYPE( int get_set_volume
, (struct volume_level
*level
, int flag
));
7 FORWARD
_PROTOTYPE( int get_set_input
, (struct inout_ctrl
*input
, int flag
, int channel
));
8 FORWARD
_PROTOTYPE( int get_set_output
, (struct inout_ctrl
*output
, int flag
));
13 /*=========================================================================*
15 *=========================================================================*/
16 PUBLIC
int mixer_ioctl(int request
, void *val
, int *len
) {
20 case MIXIOGETVOLUME
: status
= get_set_volume(val
, 0); break;
21 case MIXIOSETVOLUME
: status
= get_set_volume(val
, 1); break;
22 case MIXIOGETINPUTLEFT
: status
= get_set_input(val
, 0, 0); break;
23 case MIXIOGETINPUTRIGHT
: status
= get_set_input(val
, 0, 1); break;
24 case MIXIOGETOUTPUT
: status
= get_set_output(val
, 0); break;
25 case MIXIOSETINPUTLEFT
: status
= get_set_input(val
, 1, 0); break;
26 case MIXIOSETINPUTRIGHT
: status
= get_set_input(val
, 1, 1); break;
27 case MIXIOSETOUTPUT
: status
= get_set_output(val
, 1); break;
28 default: status
= ENOTTY
;
35 /*=========================================================================*
37 *=========================================================================*/
38 PUBLIC
int mixer_init() {
39 /* Try to detect the mixer by writing to MIXER_DAC_LEVEL if the
40 * value written can be read back the mixer is there
43 mixer_set(MIXER_DAC_LEVEL
, 0x10); /* write something to it */
44 if(mixer_get(MIXER_DAC_LEVEL
) != 0x10) {
45 dprint("sb16: Mixer not detected\n");
49 /* Enable Automatic Gain Control */
50 mixer_set(MIXER_AGC
, 0x01);
52 dprint("Mixer detected\n");
59 /*=========================================================================*
61 *=========================================================================*/
62 PRIVATE
int get_set_volume(struct volume_level
*level
, int flag
) {
63 int cmd_left
, cmd_right
, shift
, max_level
;
67 switch(level
->device
) {
69 cmd_left
= MIXER_MASTER_LEFT
;
70 cmd_right
= MIXER_MASTER_RIGHT
;
73 cmd_left
= MIXER_DAC_LEFT
;
74 cmd_right
= MIXER_DAC_RIGHT
;
77 cmd_left
= MIXER_FM_LEFT
;
78 cmd_right
= MIXER_FM_RIGHT
;
81 cmd_left
= MIXER_CD_LEFT
;
82 cmd_right
= MIXER_CD_RIGHT
;
85 cmd_left
= MIXER_LINE_LEFT
;
86 cmd_right
= MIXER_LINE_RIGHT
;
89 cmd_left
= cmd_right
= MIXER_MIC_LEVEL
;
92 cmd_left
= cmd_right
= MIXER_PC_LEVEL
;
97 cmd_left
= MIXER_TREBLE_LEFT
;
98 cmd_right
= MIXER_TREBLE_RIGHT
;
103 cmd_left
= MIXER_BASS_LEFT
;
104 cmd_right
= MIXER_BASS_RIGHT
;
112 if(flag
) { /* Set volume level */
113 if(level
->right
< 0) level
->right
= 0;
114 else if(level
->right
> max_level
) level
->right
= max_level
;
115 if(level
->left
< 0) level
->left
= 0;
116 else if(level
->left
> max_level
) level
->left
= max_level
;
118 mixer_set(cmd_right
, (level
->right
<< shift
));
119 mixer_set(cmd_left
, (level
->left
<< shift
));
120 } else { /* Get volume level */
121 level
->left
= mixer_get(cmd_left
);
122 level
->right
= mixer_get(cmd_right
);
124 level
->left
>>= shift
;
125 level
->right
>>= shift
;
132 /*=========================================================================*
134 *=========================================================================*/
135 PRIVATE
int get_set_input(struct inout_ctrl
*input
, int flag
, int channel
) {
136 int input_cmd
, input_mask
, mask
, del_mask
, shift
;
138 input_cmd
= (channel
== 0 ? MIXER_IN_LEFT
: MIXER_IN_RIGHT
);
140 mask
= mixer_get(input_cmd
);
142 switch (input
->device
) {
163 if (flag
) { /* Set input */
164 input_mask
= ((input
->left
== ON
? 1 : 0) << 1) | (input
->right
== ON
? 1 : 0);
166 if (shift
> 0) input_mask
<<= shift
;
167 else input_mask
>>= 1;
172 mixer_set(input_cmd
, mask
);
173 } else { /* Get input */
175 input
->left
= ((mask
>> (shift
+1)) & 1 == 1 ? ON
: OFF
);
176 input
->right
= ((mask
>> shift
) & 1 == 1 ? ON
: OFF
);
178 input
->left
= ((mask
& 1) == 1 ? ON
: OFF
);
186 /*=========================================================================*
188 *=========================================================================*/
189 PRIVATE
int get_set_output(struct inout_ctrl
*output
, int flag
) {
190 int output_mask
, mask
, del_mask
, shift
;
192 mask
= mixer_get(MIXER_OUTPUT_CTRL
);
194 switch (output
->device
) {
211 if (flag
) { /* Set input */
212 output_mask
= ((output
->left
== ON
? 1 : 0) << 1) | (output
->right
== ON
? 1 : 0);
214 if (shift
> 0) output_mask
<<= shift
;
215 else output_mask
>>= 1;
220 mixer_set(MIXER_OUTPUT_CTRL
, mask
);
221 } else { /* Get input */
223 output
->left
= ((mask
>> (shift
+1)) & 1 == 1 ? ON
: OFF
);
224 output
->right
= ((mask
>> shift
) & 1 == 1 ? ON
: OFF
);
226 output
->left
= ((mask
& 1) == 1 ? ON
: OFF
);
235 PUBLIC
int mixer_set(int reg
, int data
) {
238 sb16_outb(MIXER_REG
, reg
);
239 for(i
= 0; i
< 100; i
++);
240 sb16_outb(MIXER_DATA
, data
);
247 PUBLIC
int mixer_get(int reg
) {
250 sb16_outb(MIXER_REG
, reg
);
251 for(i
= 0; i
< 100; i
++);
252 return sb16_inb(MIXER_DATA
) & 0xff;