6 static int get_set_volume(struct volume_level
*level
, int flag
);
7 static int get_set_input(struct inout_ctrl
*input
, int flag
, int
9 static int get_set_output(struct inout_ctrl
*output
, int flag
);
14 /*=========================================================================*
16 *=========================================================================*/
17 int mixer_ioctl(int request
, void *val
, int *UNUSED(len
)) {
21 case MIXIOGETVOLUME
: status
= get_set_volume(val
, 0); break;
22 case MIXIOSETVOLUME
: status
= get_set_volume(val
, 1); break;
23 case MIXIOGETINPUTLEFT
: status
= get_set_input(val
, 0, 0); break;
24 case MIXIOGETINPUTRIGHT
: status
= get_set_input(val
, 0, 1); break;
25 case MIXIOGETOUTPUT
: status
= get_set_output(val
, 0); break;
26 case MIXIOSETINPUTLEFT
: status
= get_set_input(val
, 1, 0); break;
27 case MIXIOSETINPUTRIGHT
: status
= get_set_input(val
, 1, 1); break;
28 case MIXIOSETOUTPUT
: status
= get_set_output(val
, 1); break;
29 default: status
= ENOTTY
;
36 /*=========================================================================*
38 *=========================================================================*/
40 /* Try to detect the mixer by writing to MIXER_DAC_LEVEL if the
41 * value written can be read back the mixer is there
44 mixer_set(MIXER_DAC_LEVEL
, 0x10); /* write something to it */
45 if(mixer_get(MIXER_DAC_LEVEL
) != 0x10) {
46 Dprint(("sb16: Mixer not detected\n"));
50 /* Enable Automatic Gain Control */
51 mixer_set(MIXER_AGC
, 0x01);
53 Dprint(("Mixer detected\n"));
60 /*=========================================================================*
62 *=========================================================================*/
63 static int get_set_volume(struct volume_level
*level
, int flag
) {
64 int cmd_left
, cmd_right
, shift
, max_level
;
68 switch(level
->device
) {
70 cmd_left
= MIXER_MASTER_LEFT
;
71 cmd_right
= MIXER_MASTER_RIGHT
;
74 cmd_left
= MIXER_DAC_LEFT
;
75 cmd_right
= MIXER_DAC_RIGHT
;
78 cmd_left
= MIXER_FM_LEFT
;
79 cmd_right
= MIXER_FM_RIGHT
;
82 cmd_left
= MIXER_CD_LEFT
;
83 cmd_right
= MIXER_CD_RIGHT
;
86 cmd_left
= MIXER_LINE_LEFT
;
87 cmd_right
= MIXER_LINE_RIGHT
;
90 cmd_left
= cmd_right
= MIXER_MIC_LEVEL
;
93 cmd_left
= cmd_right
= MIXER_PC_LEVEL
;
98 cmd_left
= MIXER_TREBLE_LEFT
;
99 cmd_right
= MIXER_TREBLE_RIGHT
;
104 cmd_left
= MIXER_BASS_LEFT
;
105 cmd_right
= MIXER_BASS_RIGHT
;
113 if(flag
) { /* Set volume level */
114 if(level
->right
< 0) level
->right
= 0;
115 else if(level
->right
> max_level
) level
->right
= max_level
;
116 if(level
->left
< 0) level
->left
= 0;
117 else if(level
->left
> max_level
) level
->left
= max_level
;
119 mixer_set(cmd_right
, (level
->right
<< shift
));
120 mixer_set(cmd_left
, (level
->left
<< shift
));
121 } else { /* Get volume level */
122 level
->left
= mixer_get(cmd_left
);
123 level
->right
= mixer_get(cmd_right
);
125 level
->left
>>= shift
;
126 level
->right
>>= shift
;
133 /*=========================================================================*
135 *=========================================================================*/
136 static int get_set_input(struct inout_ctrl
*input
, int flag
, int channel
) {
137 int input_cmd
, input_mask
, mask
, del_mask
, shift
;
139 input_cmd
= (channel
== 0 ? MIXER_IN_LEFT
: MIXER_IN_RIGHT
);
141 mask
= mixer_get(input_cmd
);
143 switch (input
->device
) {
164 if (flag
) { /* Set input */
165 input_mask
= ((input
->left
== ON
? 1 : 0) << 1) | (input
->right
== ON
? 1 : 0);
167 if (shift
> 0) input_mask
<<= shift
;
168 else input_mask
>>= 1;
173 mixer_set(input_cmd
, mask
);
174 } else { /* Get input */
176 input
->left
= (((mask
>> (shift
+1)) & 1) == 1 ? ON
: OFF
);
177 input
->right
= (((mask
>> shift
) & 1) == 1 ? ON
: OFF
);
179 input
->left
= ((mask
& 1) == 1 ? ON
: OFF
);
187 /*=========================================================================*
189 *=========================================================================*/
190 static int get_set_output(struct inout_ctrl
*output
, int flag
) {
191 int output_mask
, mask
, del_mask
, shift
;
193 mask
= mixer_get(MIXER_OUTPUT_CTRL
);
195 switch (output
->device
) {
212 if (flag
) { /* Set input */
213 output_mask
= ((output
->left
== ON
? 1 : 0) << 1) | (output
->right
== ON
? 1 : 0);
215 if (shift
> 0) output_mask
<<= shift
;
216 else output_mask
>>= 1;
221 mixer_set(MIXER_OUTPUT_CTRL
, mask
);
222 } else { /* Get input */
224 output
->left
= (((mask
>> (shift
+1)) & 1) == 1 ? ON
: OFF
);
225 output
->right
= (((mask
>> shift
) & 1) == 1 ? ON
: OFF
);
227 output
->left
= ((mask
& 1) == 1 ? ON
: OFF
);
236 int mixer_set(int reg
, int data
) {
239 sb16_outb(MIXER_REG
, reg
);
240 for(i
= 0; i
< 100; i
++);
241 sb16_outb(MIXER_DATA
, data
);
248 int mixer_get(int reg
) {
251 sb16_outb(MIXER_REG
, reg
);
252 for(i
= 0; i
< 100; i
++);
253 return sb16_inb(MIXER_DATA
) & 0xff;