00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "sb16.h"
00025
00026
00027 _PROTOTYPE(void main, (void));
00028 FORWARD _PROTOTYPE( int mixer_init, (void));
00029 FORWARD _PROTOTYPE( int mixer_open, (message *m_ptr));
00030 FORWARD _PROTOTYPE( int mixer_close, (message *m_ptr));
00031 FORWARD _PROTOTYPE( int mixer_ioctl, (message *m_ptr));
00032 FORWARD _PROTOTYPE( int mixer_get, (int reg));
00033 FORWARD _PROTOTYPE( int get_set_volume, (message *m_ptr, int flag));
00034 FORWARD _PROTOTYPE( int get_set_input, (message *m_ptr, int flag, int channel));
00035 FORWARD _PROTOTYPE( int get_set_output, (message *m_ptr, int flag));
00036
00037
00038 PRIVATE int mixer_avail = 0;
00039
00040
00041 #define dprint (void)
00042
00043
00044
00045
00046
00047 PUBLIC void main() {
00048 message mess;
00049 int err, caller, proc_nr;
00050
00051
00052
00053
00054 while (TRUE) {
00055 receive(ANY, &mess);
00056
00057 caller = mess.m_source;
00058 proc_nr = mess.IO_ENDPT;
00059
00060 switch (caller) {
00061 case HARDWARE:
00062 continue;
00063 case FS_PROC_NR:
00064 break;
00065 default:
00066 dprint("sb16: got message from %d\n", caller);
00067 continue;
00068 }
00069
00070
00071 switch(mess.m_type) {
00072 case DEV_OPEN: err = mixer_open(&mess); break;
00073 case DEV_CLOSE: err = mixer_close(&mess); break;
00074 case DEV_IOCTL: err = mixer_ioctl(&mess); break;
00075 default: err = EINVAL; break;
00076 }
00077
00078
00079 mess.m_type = TASK_REPLY;
00080 mess.REP_ENDPT = proc_nr;
00081
00082 dprint("%d %d", err, OK);
00083
00084 mess.REP_STATUS = err;
00085 send(caller, &mess);
00086 }
00087 }
00088
00089
00090
00091
00092
00093 PRIVATE int mixer_open(m_ptr)
00094 message *m_ptr;
00095 {
00096 dprint("mixer_open\n");
00097
00098
00099 if (!mixer_avail && mixer_init() != OK) return EIO;
00100
00101 return OK;
00102 }
00103
00104
00105
00106
00107
00108 PRIVATE int mixer_close(m_ptr)
00109 message *m_ptr;
00110 {
00111 dprint("mixer_close\n");
00112
00113 return OK;
00114 }
00115
00116
00117
00118
00119
00120 PRIVATE int mixer_ioctl(m_ptr)
00121 message *m_ptr;
00122 {
00123 int status;
00124
00125 dprint("mixer: got ioctl %d\n", m_ptr->REQUEST);
00126
00127
00128 switch(m_ptr->REQUEST) {
00129 case MIXIOGETVOLUME: status = get_set_volume(m_ptr, 0); break;
00130 case MIXIOSETVOLUME: status = get_set_volume(m_ptr, 1); break;
00131 case MIXIOGETINPUTLEFT: status = get_set_input(m_ptr, 0, 0); break;
00132 case MIXIOGETINPUTRIGHT: status = get_set_input(m_ptr, 0, 1); break;
00133 case MIXIOGETOUTPUT: status = get_set_output(m_ptr, 0); break;
00134 case MIXIOSETINPUTLEFT: status = get_set_input(m_ptr, 1, 0); break;
00135 case MIXIOSETINPUTRIGHT: status = get_set_input(m_ptr, 1, 1); break;
00136 case MIXIOSETOUTPUT: status = get_set_output(m_ptr, 1); break;
00137 default: status = ENOTTY;
00138 }
00139
00140 return status;
00141 }
00142
00143
00144
00145
00146
00147 PRIVATE int mixer_init()
00148 {
00149
00150
00151
00152
00153 mixer_set(MIXER_DAC_LEVEL, 0x10);
00154 if(mixer_get(MIXER_DAC_LEVEL) != 0x10) {
00155 dprint("sb16: Mixer not detected\n");
00156 return EIO;
00157 }
00158
00159
00160 mixer_set(MIXER_AGC, 0x01);
00161
00162 dprint("Mixer detected\n");
00163
00164 mixer_avail = 1;
00165 return OK;
00166 }
00167
00168
00169
00170
00171
00172 PRIVATE int mixer_get(reg)
00173 int reg;
00174 {
00175 int i;
00176
00177 sb16_outb(MIXER_REG, reg);
00178 for(i = 0; i < 100; i++);
00179 return sb16_inb(MIXER_DATA) & 0xff;
00180 }
00181
00182
00183
00184
00185
00186 PRIVATE int get_set_volume(m_ptr, flag)
00187 message *m_ptr;
00188 int flag;
00189 {
00190 phys_bytes user_phys;
00191 struct volume_level level;
00192 int cmd_left, cmd_right, shift, max_level;
00193
00194 sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&level, (phys_bytes)sizeof(level));
00195
00196 shift = 3;
00197 max_level = 0x1F;
00198
00199 switch(level.device) {
00200 case Master:
00201 cmd_left = MIXER_MASTER_LEFT;
00202 cmd_right = MIXER_MASTER_RIGHT;
00203 break;
00204 case Dac:
00205 cmd_left = MIXER_DAC_LEFT;
00206 cmd_right = MIXER_DAC_RIGHT;
00207 break;
00208 case Fm:
00209 cmd_left = MIXER_FM_LEFT;
00210 cmd_right = MIXER_FM_RIGHT;
00211 break;
00212 case Cd:
00213 cmd_left = MIXER_CD_LEFT;
00214 cmd_right = MIXER_CD_RIGHT;
00215 break;
00216 case Line:
00217 cmd_left = MIXER_LINE_LEFT;
00218 cmd_right = MIXER_LINE_RIGHT;
00219 break;
00220 case Mic:
00221 cmd_left = cmd_right = MIXER_MIC_LEVEL;
00222 break;
00223 case Speaker:
00224 cmd_left = cmd_right = MIXER_PC_LEVEL;
00225 shift = 6;
00226 max_level = 0x03;
00227 break;
00228 case Treble:
00229 cmd_left = MIXER_TREBLE_LEFT;
00230 cmd_right = MIXER_TREBLE_RIGHT;
00231 shift = 4;
00232 max_level = 0x0F;
00233 break;
00234 case Bass:
00235 cmd_left = MIXER_BASS_LEFT;
00236 cmd_right = MIXER_BASS_RIGHT;
00237 shift = 4;
00238 max_level = 0x0F;
00239 break;
00240 default:
00241 return EINVAL;
00242 }
00243
00244 if(flag) {
00245 if(level.right < 0) level.right = 0;
00246 else if(level.right > max_level) level.right = max_level;
00247 if(level.left < 0) level.left = 0;
00248 else if(level.left > max_level) level.left = max_level;
00249
00250 mixer_set(cmd_right, (level.right << shift));
00251 mixer_set(cmd_left, (level.left << shift));
00252 } else {
00253 level.left = mixer_get(cmd_left);
00254 level.right = mixer_get(cmd_right);
00255
00256 level.left >>= shift;
00257 level.right >>= shift;
00258
00259
00260 sys_datacopy(SELF, (vir_bytes)&level, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(level));
00261 }
00262
00263 return OK;
00264 }
00265
00266
00267
00268
00269
00270 PRIVATE int get_set_input(m_ptr, flag, channel)
00271 message *m_ptr;
00272 int flag;
00273 int channel;
00274 {
00275 phys_bytes user_phys;
00276 struct inout_ctrl input;
00277 int input_cmd, input_mask, mask, del_mask, shift;
00278
00279 sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&input, (phys_bytes)sizeof(input));
00280
00281 input_cmd = (channel == 0 ? MIXER_IN_LEFT : MIXER_IN_RIGHT);
00282
00283 mask = mixer_get(input_cmd);
00284
00285 switch (input.device) {
00286 case Fm:
00287 shift = 5;
00288 del_mask = 0x1F;
00289 break;
00290 case Cd:
00291 shift = 1;
00292 del_mask = 0x79;
00293 break;
00294 case Line:
00295 shift = 3;
00296 del_mask = 0x67;
00297 break;
00298 case Mic:
00299 shift = 0;
00300 del_mask = 0x7E;
00301 break;
00302 default:
00303 return EINVAL;
00304 }
00305
00306 if (flag) {
00307 input_mask = ((input.left == ON ? 1 : 0) << 1) | (input.right == ON ? 1 : 0);
00308
00309 if (shift > 0) input_mask <<= shift;
00310 else input_mask >>= 1;
00311
00312 mask &= del_mask;
00313 mask |= input_mask;
00314
00315 mixer_set(input_cmd, mask);
00316 } else {
00317 if (shift > 0) {
00318 input.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
00319 input.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
00320 } else {
00321 input.left = ((mask & 1) == 1 ? ON : OFF);
00322 }
00323
00324
00325 sys_datacopy(SELF, (vir_bytes)&input, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(input));
00326 }
00327
00328 return OK;
00329 }
00330
00331
00332
00333
00334
00335 PRIVATE int get_set_output(m_ptr, flag)
00336 message *m_ptr;
00337 int flag;
00338 {
00339 phys_bytes user_phys;
00340 struct inout_ctrl output;
00341 int output_mask, mask, del_mask, shift;
00342
00343 sys_datacopy(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)&output, (phys_bytes)sizeof(output));
00344
00345 mask = mixer_get(MIXER_OUTPUT_CTRL);
00346
00347 switch (output.device) {
00348 case Cd:
00349 shift = 1;
00350 del_mask = 0x79;
00351 break;
00352 case Line:
00353 shift = 3;
00354 del_mask = 0x67;
00355 break;
00356 case Mic:
00357 shift = 0;
00358 del_mask = 0x7E;
00359 break;
00360 default:
00361 return EINVAL;
00362 }
00363
00364 if (flag) {
00365 output_mask = ((output.left == ON ? 1 : 0) << 1) | (output.right == ON ? 1 : 0);
00366
00367 if (shift > 0) output_mask <<= shift;
00368 else output_mask >>= 1;
00369
00370 mask &= del_mask;
00371 mask |= output_mask;
00372
00373 mixer_set(MIXER_OUTPUT_CTRL, mask);
00374 } else {
00375 if (shift > 0) {
00376 output.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
00377 output.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
00378 } else {
00379 output.left = ((mask & 1) == 1 ? ON : OFF);
00380 }
00381
00382
00383 sys_datacopy(SELF, (vir_bytes)&output, m_ptr->IO_ENDPT, (vir_bytes)m_ptr->ADDRESS, (phys_bytes)sizeof(output));
00384 }
00385
00386 return OK;
00387 }