1 /* 2 * Auich BeOS Driver for Intel Southbridge audio 3 * 4 * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr) 5 * 6 * Original code : BeOS Driver for Intel ICH AC'97 Link interface 7 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de> 8 * 9 * All rights reserved. 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * - Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * - Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 28 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32 #include <OS.h> 33 #include <MediaDefs.h> 34 #include <strings.h> 35 #include "multi_audio.h" 36 #include "multi.h" 37 #include "ac97.h" 38 39 //#define DEBUG 1 40 41 #include "debug.h" 42 #include "auich.h" 43 #include "util.h" 44 #include "io.h" 45 46 static void 47 auich_ac97_get_mix(void *card, const void *cookie, int32 type, float *values) { 48 auich_dev *dev = (auich_dev*)card; 49 ac97_source_info *info = (ac97_source_info *)cookie; 50 uint16 value, mask; 51 float gain; 52 53 switch(type) { 54 case B_MIX_GAIN: 55 value = auich_codec_read(&dev->config, info->reg); 56 //PRINT(("B_MIX_GAIN value : %u\n", value)); 57 if(info->type & B_MIX_STEREO) { 58 mask = ((1 << (info->bits + 1)) - 1) << 8; 59 gain = ((value & mask) >> 8) * info->granularity; 60 if(info->polarity == 1) 61 values[0] = info->max_gain - gain; 62 else 63 values[0] = gain - info->min_gain; 64 65 mask = ((1 << (info->bits + 1)) - 1); 66 gain = (value & mask) * info->granularity; 67 if(info->polarity == 1) 68 values[1] = info->max_gain - gain; 69 else 70 values[1] = gain - info->min_gain; 71 } else { 72 mask = ((1 << (info->bits + 1)) - 1); 73 gain = (value & mask) * info->granularity; 74 if(info->polarity == 1) 75 values[0] = info->max_gain - gain; 76 else 77 values[0] = gain - info->min_gain; 78 } 79 break; 80 case B_MIX_MUTE: 81 mask = ((1 << 1) - 1) << 15; 82 value = auich_codec_read(&dev->config, info->reg); 83 //PRINT(("B_MIX_MUTE value : %u\n", value)); 84 value &= mask; 85 values[0] = ((value >> 15) == 1) ? 1.0 : 0.0; 86 break; 87 case B_MIX_MICBOOST: 88 mask = ((1 << 1) - 1) << 6; 89 value = auich_codec_read(&dev->config, info->reg); 90 //PRINT(("B_MIX_MICBOOST value : %u\n", value)); 91 value &= mask; 92 values[0] = ((value >> 6) == 1) ? 1.0 : 0.0; 93 break; 94 case B_MIX_MUX: 95 mask = ((1 << 3) - 1); 96 value = auich_codec_read(&dev->config, AC97_RECORD_SELECT); 97 value &= mask; 98 //PRINT(("B_MIX_MUX value : %u\n", value)); 99 values[0] = (float)value; 100 break; 101 } 102 } 103 104 static void 105 auich_ac97_set_mix(void *card, const void *cookie, int32 type, float *values) { 106 auich_dev *dev = (auich_dev*)card; 107 ac97_source_info *info = (ac97_source_info *)cookie; 108 uint16 value, mask; 109 float gain; 110 111 switch(type) { 112 case B_MIX_GAIN: 113 value = auich_codec_read(&dev->config, info->reg); 114 if(info->type & B_MIX_STEREO) { 115 mask = ((1 << (info->bits + 1)) - 1) << 8; 116 value &= ~mask; 117 118 if(info->polarity == 1) 119 gain = info->max_gain - values[0]; 120 else 121 gain = values[0] - info->min_gain; 122 value |= ((uint16)(gain / info->granularity) << 8) & mask; 123 124 mask = ((1 << (info->bits + 1)) - 1); 125 value &= ~mask; 126 if(info->polarity == 1) 127 gain = info->max_gain - values[1]; 128 else 129 gain = values[1] - info->min_gain; 130 value |= ((uint16)(gain / info->granularity)) & mask; 131 } else { 132 mask = ((1 << (info->bits + 1)) - 1); 133 value &= ~mask; 134 if(info->polarity == 1) 135 gain = info->max_gain - values[0]; 136 else 137 gain = values[0] - info->min_gain; 138 value |= ((uint16)(gain / info->granularity)) & mask; 139 } 140 //PRINT(("B_MIX_GAIN value : %u\n", value)); 141 auich_codec_write(&dev->config, info->reg, value); 142 break; 143 case B_MIX_MUTE: 144 mask = ((1 << 1) - 1) << 15; 145 value = auich_codec_read(&dev->config, info->reg); 146 value &= ~mask; 147 value |= ((values[0] == 1.0 ? 1 : 0 ) << 15 & mask); 148 if(info->reg == AC97_SURROUND_VOLUME) { 149 // there is a independent mute for each channel 150 mask = ((1 << 1) - 1) << 7; 151 value &= ~mask; 152 value |= ((values[0] == 1.0 ? 1 : 0 ) << 7 & mask); 153 } 154 //PRINT(("B_MIX_MUTE value : %u\n", value)); 155 auich_codec_write(&dev->config, info->reg, value); 156 break; 157 case B_MIX_MICBOOST: 158 mask = ((1 << 1) - 1) << 6; 159 value = auich_codec_read(&dev->config, info->reg); 160 value &= ~mask; 161 value |= ((values[0] == 1.0 ? 1 : 0 ) << 6 & mask); 162 //PRINT(("B_MIX_MICBOOST value : %u\n", value)); 163 auich_codec_write(&dev->config, info->reg, value); 164 break; 165 case B_MIX_MUX: 166 mask = ((1 << 3) - 1); 167 value = ((int32)values[0]) & mask; 168 value = value | (value << 8); 169 //PRINT(("B_MIX_MUX value : %u\n", value)); 170 auich_codec_write(&dev->config, AC97_RECORD_SELECT, value); 171 break; 172 } 173 174 } 175 176 static int32 177 auich_create_group_control(multi_dev *multi, int32 *index, int32 parent, 178 int32 string, const char* name) { 179 int32 i = *index; 180 (*index)++; 181 multi->controls[i].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + i; 182 multi->controls[i].mix_control.parent = parent; 183 multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP; 184 multi->controls[i].mix_control.master = EMU_MULTI_CONTROL_MASTERID; 185 multi->controls[i].mix_control.string = string; 186 if(name) 187 strcpy(multi->controls[i].mix_control.name, name); 188 189 return multi->controls[i].mix_control.id; 190 } 191 192 static status_t 193 auich_create_controls_list(multi_dev *multi) 194 { 195 uint32 i = 0, index = 0, count, id, parent, parent2, parent3; 196 const ac97_source_info *info; 197 198 parent = auich_create_group_control(multi, &index, 0, 0, "Record"); 199 200 /* AC97 Record */ 201 info = &source_info[0]; 202 PRINT(("name : %s\n", info->name)); 203 204 parent2 = auich_create_group_control(multi, &index, parent, 0, info->name); 205 206 if(info->type & B_MIX_GAIN) { 207 if(info->type & B_MIX_MUTE) { 208 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 209 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE; 210 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID; 211 multi->controls[index].mix_control.parent = parent2; 212 multi->controls[index].mix_control.string = S_MUTE; 213 multi->controls[index].cookie = info; 214 multi->controls[index].type = B_MIX_MUTE; 215 multi->controls[index].get = &auich_ac97_get_mix; 216 multi->controls[index].set = &auich_ac97_set_mix; 217 index++; 218 } 219 220 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 221 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 222 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID; 223 multi->controls[index].mix_control.parent = parent2; 224 strcpy(multi->controls[index].mix_control.name, info->name); 225 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain; 226 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain; 227 multi->controls[index].mix_control.u.gain.granularity = info->granularity; 228 multi->controls[index].cookie = info; 229 multi->controls[index].type = B_MIX_GAIN; 230 multi->controls[index].get = &auich_ac97_get_mix; 231 multi->controls[index].set = &auich_ac97_set_mix; 232 id = multi->controls[index].mix_control.id; 233 index++; 234 235 if(info->type & B_MIX_STEREO) { 236 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 237 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 238 multi->controls[index].mix_control.master = id; 239 multi->controls[index].mix_control.parent = parent2; 240 strcpy(multi->controls[index].mix_control.name, info->name); 241 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain; 242 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain; 243 multi->controls[index].mix_control.u.gain.granularity = info->granularity; 244 multi->controls[index].cookie = info; 245 multi->controls[index].type = B_MIX_GAIN; 246 multi->controls[index].get = &auich_ac97_get_mix; 247 multi->controls[index].set = &auich_ac97_set_mix; 248 index++; 249 } 250 251 if(info->type & B_MIX_RECORDMUX) { 252 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 253 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX; 254 multi->controls[index].mix_control.parent = parent2; 255 strcpy(multi->controls[index].mix_control.name, "Record Mux"); 256 multi->controls[index].cookie = info; 257 multi->controls[index].type = B_MIX_MUX; 258 multi->controls[index].get = &auich_ac97_get_mix; 259 multi->controls[index].set = &auich_ac97_set_mix; 260 parent3 = multi->controls[index].mix_control.id; 261 index++; 262 263 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 264 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 265 multi->controls[index].mix_control.parent = parent3; 266 multi->controls[index].mix_control.string = S_MIC; 267 index++; 268 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 269 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 270 multi->controls[index].mix_control.parent = parent3; 271 strcpy(multi->controls[index].mix_control.name, "CD In"); 272 index++; 273 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 274 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 275 multi->controls[index].mix_control.parent = parent3; 276 strcpy(multi->controls[index].mix_control.name, "Video In"); 277 index++; 278 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 279 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 280 multi->controls[index].mix_control.parent = parent3; 281 strcpy(multi->controls[index].mix_control.name, "Aux In"); 282 index++; 283 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 284 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 285 multi->controls[index].mix_control.parent = parent3; 286 strcpy(multi->controls[index].mix_control.name, "Line In"); 287 index++; 288 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 289 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 290 multi->controls[index].mix_control.parent = parent3; 291 multi->controls[index].mix_control.string = S_STEREO_MIX; 292 index++; 293 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 294 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 295 multi->controls[index].mix_control.parent = parent3; 296 multi->controls[index].mix_control.string = S_MONO_MIX; 297 index++; 298 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 299 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 300 multi->controls[index].mix_control.parent = parent3; 301 strcpy(multi->controls[index].mix_control.name, "TAD"); 302 index++; 303 } 304 } 305 306 parent = auich_create_group_control(multi, &index, 0, 0, "AC97 Mixer"); 307 308 count = source_info_size; 309 count--; 310 311 for(i=1; i < count ; i++) { 312 info = &source_info[i]; 313 PRINT(("name : %s\n", info->name)); 314 315 parent2 = auich_create_group_control(multi, &index, parent, 0, info->name); 316 317 if(info->type & B_MIX_GAIN) { 318 if(info->type & B_MIX_MUTE) { 319 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 320 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE; 321 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID; 322 multi->controls[index].mix_control.parent = parent2; 323 multi->controls[index].mix_control.string = S_MUTE; 324 multi->controls[index].cookie = info; 325 multi->controls[index].type = B_MIX_MUTE; 326 multi->controls[index].get = &auich_ac97_get_mix; 327 multi->controls[index].set = &auich_ac97_set_mix; 328 index++; 329 } 330 331 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 332 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 333 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID; 334 multi->controls[index].mix_control.parent = parent2; 335 strcpy(multi->controls[index].mix_control.name, info->name); 336 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain; 337 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain; 338 multi->controls[index].mix_control.u.gain.granularity = info->granularity; 339 multi->controls[index].cookie = info; 340 multi->controls[index].type = B_MIX_GAIN; 341 multi->controls[index].get = &auich_ac97_get_mix; 342 multi->controls[index].set = &auich_ac97_set_mix; 343 id = multi->controls[index].mix_control.id; 344 index++; 345 346 if(info->type & B_MIX_STEREO) { 347 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 348 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 349 multi->controls[index].mix_control.master = id; 350 multi->controls[index].mix_control.parent = parent2; 351 strcpy(multi->controls[index].mix_control.name, info->name); 352 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain; 353 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain; 354 multi->controls[index].mix_control.u.gain.granularity = info->granularity; 355 multi->controls[index].cookie = info; 356 multi->controls[index].type = B_MIX_GAIN; 357 multi->controls[index].get = &auich_ac97_get_mix; 358 multi->controls[index].set = &auich_ac97_set_mix; 359 index++; 360 } 361 } 362 } 363 364 parent = auich_create_group_control(multi, &index, 0, S_SETUP, NULL); 365 366 /* AC97 20db Boost Mic */ 367 info = &source_info[6]; 368 369 if(info->type & B_MIX_GAIN && info->type & B_MIX_MICBOOST) { 370 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index; 371 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE; 372 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID; 373 multi->controls[index].mix_control.parent = parent; 374 strcpy(multi->controls[index].mix_control.name, "Mic +20dB"); 375 multi->controls[index].cookie = info; 376 multi->controls[index].type = B_MIX_MICBOOST; 377 multi->controls[index].get = &auich_ac97_get_mix; 378 multi->controls[index].set = &auich_ac97_set_mix; 379 index++; 380 } 381 382 multi->control_count = index; 383 PRINT(("multi->control_count %lu\n", multi->control_count)); 384 return B_OK; 385 } 386 387 static status_t 388 auich_get_mix(auich_dev *card, multi_mix_value_info * MMVI) 389 { 390 int32 i, id; 391 multi_mixer_control *control = NULL; 392 for(i=0; i<MMVI->item_count; i++) { 393 id = MMVI->values[i].id - EMU_MULTI_CONTROL_FIRSTID; 394 if(id < 0 || id >= card->multi.control_count) { 395 PRINT(("auich_get_mix : invalid control id requested : %li\n", id)); 396 continue; 397 } 398 control = &card->multi.controls[id]; 399 400 if(control->mix_control.flags & B_MULTI_MIX_GAIN) { 401 if(control->get) { 402 float values[2]; 403 control->get(card, control->cookie, control->type, values); 404 if(control->mix_control.master == EMU_MULTI_CONTROL_MASTERID) 405 MMVI->values[i].u.gain = values[0]; 406 else 407 MMVI->values[i].u.gain = values[1]; 408 } 409 } 410 411 if(control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) { 412 float values[1]; 413 control->get(card, control->cookie, control->type, values); 414 MMVI->values[i].u.enable = (values[0] == 1.0); 415 } 416 417 if(control->mix_control.flags & B_MULTI_MIX_MUX && control->get) { 418 float values[1]; 419 control->get(card, control->cookie, control->type, values); 420 MMVI->values[i].u.mux = (int32)values[0]; 421 } 422 } 423 return B_OK; 424 } 425 426 static status_t 427 auich_set_mix(auich_dev *card, multi_mix_value_info * MMVI) 428 { 429 int32 i, id; 430 multi_mixer_control *control = NULL; 431 for(i=0; i<MMVI->item_count; i++) { 432 id = MMVI->values[i].id - EMU_MULTI_CONTROL_FIRSTID; 433 if(id < 0 || id >= card->multi.control_count) { 434 PRINT(("auich_set_mix : invalid control id requested : %li\n", id)); 435 continue; 436 } 437 control = &card->multi.controls[id]; 438 439 if(control->mix_control.flags & B_MULTI_MIX_GAIN) { 440 multi_mixer_control *control2 = NULL; 441 if(i+1<MMVI->item_count) { 442 id = MMVI->values[i + 1].id - EMU_MULTI_CONTROL_FIRSTID; 443 if(id < 0 || id >= card->multi.control_count) { 444 PRINT(("auich_set_mix : invalid control id requested : %li\n", id)); 445 } else { 446 control2 = &card->multi.controls[id]; 447 if(control2->mix_control.master != control->mix_control.id) 448 control2 = NULL; 449 } 450 } 451 452 if(control->set) { 453 float values[2]; 454 values[0] = 0.0; 455 values[1] = 0.0; 456 457 if(control->mix_control.master == EMU_MULTI_CONTROL_MASTERID) 458 values[0] = MMVI->values[i].u.gain; 459 else 460 values[1] = MMVI->values[i].u.gain; 461 462 if(control2 && control2->mix_control.master != EMU_MULTI_CONTROL_MASTERID) 463 values[1] = MMVI->values[i+1].u.gain; 464 465 control->set(card, control->cookie, control->type, values); 466 } 467 468 if(control2) 469 i++; 470 } 471 472 if(control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) { 473 float values[1]; 474 475 values[0] = MMVI->values[i].u.enable ? 1.0 : 0.0; 476 control->set(card, control->cookie, control->type, values); 477 } 478 479 if(control->mix_control.flags & B_MULTI_MIX_MUX && control->set) { 480 float values[1]; 481 482 values[0] = (float)MMVI->values[i].u.mux; 483 control->set(card, control->cookie, control->type, values); 484 } 485 } 486 return B_OK; 487 } 488 489 static status_t 490 auich_list_mix_controls(auich_dev *card, multi_mix_control_info * MMCI) 491 { 492 multi_mix_control *MMC; 493 int32 i; 494 495 MMC = MMCI->controls; 496 if(MMCI->control_count < 24) 497 return B_ERROR; 498 499 if(auich_create_controls_list(&card->multi) < B_OK) 500 return B_ERROR; 501 for(i=0; i<card->multi.control_count; i++) { 502 MMC[i] = card->multi.controls[i].mix_control; 503 } 504 505 MMCI->control_count = card->multi.control_count; 506 return B_OK; 507 } 508 509 static status_t 510 auich_list_mix_connections(auich_dev *card, multi_mix_connection_info * data) 511 { 512 return B_ERROR; 513 } 514 515 static status_t 516 auich_list_mix_channels(auich_dev *card, multi_mix_channel_info *data) 517 { 518 return B_ERROR; 519 } 520 521 /*multi_channel_info chans[] = { 522 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 523 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 524 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 525 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 526 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 527 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 528 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 529 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 530 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 531 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 532 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 533 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 534 };*/ 535 536 /*multi_channel_info chans[] = { 537 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 538 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 539 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 }, 540 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 }, 541 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 }, 542 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 }, 543 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 544 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 545 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 546 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 547 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 548 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 549 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 550 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 551 };*/ 552 553 554 static void 555 auich_create_channels_list(multi_dev *multi) 556 { 557 auich_stream *stream; 558 uint32 index, i, mode, designations; 559 multi_channel_info *chans; 560 uint32 chan_designations[] = { 561 B_CHANNEL_LEFT, 562 B_CHANNEL_RIGHT, 563 B_CHANNEL_REARLEFT, 564 B_CHANNEL_REARRIGHT, 565 B_CHANNEL_CENTER, 566 B_CHANNEL_SUB 567 }; 568 569 chans = multi->chans; 570 index = 0; 571 572 for(mode=AUICH_USE_PLAY; mode!=-1; 573 mode = (mode == AUICH_USE_PLAY) ? AUICH_USE_RECORD : -1) { 574 LIST_FOREACH(stream, &((auich_dev*)multi->card)->streams, next) { 575 if ((stream->use & mode) == 0) 576 continue; 577 578 if(stream->channels == 2) 579 designations = B_CHANNEL_STEREO_BUS; 580 else 581 designations = B_CHANNEL_SURROUND_BUS; 582 583 for(i=0; i<stream->channels; i++) { 584 chans[index].channel_id = index; 585 chans[index].kind = (mode == AUICH_USE_PLAY) ? B_MULTI_OUTPUT_CHANNEL : B_MULTI_INPUT_CHANNEL; 586 chans[index].designations = designations | chan_designations[i]; 587 chans[index].connectors = 0; 588 index++; 589 } 590 } 591 592 if(mode==AUICH_USE_PLAY) { 593 multi->output_channel_count = index; 594 } else { 595 multi->input_channel_count = index - multi->output_channel_count; 596 } 597 } 598 599 chans[index].channel_id = index; 600 chans[index].kind = B_MULTI_OUTPUT_BUS; 601 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS; 602 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 603 index++; 604 605 chans[index].channel_id = index; 606 chans[index].kind = B_MULTI_OUTPUT_BUS; 607 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS; 608 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 609 index++; 610 611 multi->output_bus_channel_count = index - multi->output_channel_count 612 - multi->input_channel_count; 613 614 chans[index].channel_id = index; 615 chans[index].kind = B_MULTI_INPUT_BUS; 616 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS; 617 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 618 index++; 619 620 chans[index].channel_id = index; 621 chans[index].kind = B_MULTI_INPUT_BUS; 622 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS; 623 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 624 index++; 625 626 multi->input_bus_channel_count = index - multi->output_channel_count 627 - multi->input_channel_count - multi->output_bus_channel_count; 628 629 multi->aux_bus_channel_count = 0; 630 } 631 632 633 static status_t 634 auich_get_description(auich_dev *card, multi_description *data) 635 { 636 uint32 size; 637 638 data->interface_version = B_CURRENT_INTERFACE_VERSION; 639 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 640 641 switch(card->info.vendor_id) { 642 case INTEL_VENDOR_ID: 643 strncpy(data->friendly_name, FRIENDLY_NAME_ICH, 32); 644 break; 645 case SIS_VENDOR_ID: 646 strncpy(data->friendly_name, FRIENDLY_NAME_SIS, 32); 647 break; 648 case NVIDIA_VENDOR_ID: 649 strncpy(data->friendly_name, FRIENDLY_NAME_NVIDIA, 32); 650 break; 651 case AMD_VENDOR_ID: 652 strncpy(data->friendly_name, FRIENDLY_NAME_AMD, 32); 653 break; 654 } 655 656 strcpy(data->vendor_info, AUTHOR); 657 658 /*data->output_channel_count = 6; 659 data->input_channel_count = 4; 660 data->output_bus_channel_count = 2; 661 data->input_bus_channel_count = 2; 662 data->aux_bus_channel_count = 0;*/ 663 664 data->output_channel_count = card->multi.output_channel_count; 665 data->input_channel_count = card->multi.input_channel_count; 666 data->output_bus_channel_count = card->multi.output_bus_channel_count; 667 data->input_bus_channel_count = card->multi.input_bus_channel_count; 668 data->aux_bus_channel_count = card->multi.aux_bus_channel_count; 669 670 size = card->multi.output_channel_count + card->multi.input_channel_count 671 + card->multi.output_bus_channel_count + card->multi.input_bus_channel_count 672 + card->multi.aux_bus_channel_count; 673 674 // for each channel, starting with the first output channel, 675 // then the second, third..., followed by the first input 676 // channel, second, third, ..., followed by output bus 677 // channels and input bus channels and finally auxillary channels, 678 679 LOG(("request_channel_count = %d\n",data->request_channel_count)); 680 if (data->request_channel_count >= size) { 681 LOG(("copying data\n")); 682 memcpy(data->channels, card->multi.chans, size * sizeof(card->multi.chans[0])); 683 } 684 685 data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR; 686 data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR; 687 /*data->output_rates = B_SR_44100; 688 data->input_rates = B_SR_44100;*/ 689 data->min_cvsr_rate = 0; 690 data->max_cvsr_rate = 48000; 691 //data->max_cvsr_rate = 44100; 692 693 data->output_formats = B_FMT_16BIT; 694 data->input_formats = B_FMT_16BIT; 695 data->lock_sources = B_MULTI_LOCK_INTERNAL; 696 data->timecode_sources = 0; 697 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 698 data->start_latency = 3000; 699 700 strcpy(data->control_panel,""); 701 702 return B_OK; 703 } 704 705 static status_t 706 auich_get_enabled_channels(auich_dev *card, multi_channel_enable *data) 707 { 708 B_SET_CHANNEL(data->enable_bits, 0, true); 709 B_SET_CHANNEL(data->enable_bits, 1, true); 710 B_SET_CHANNEL(data->enable_bits, 2, true); 711 B_SET_CHANNEL(data->enable_bits, 3, true); 712 data->lock_source = B_MULTI_LOCK_INTERNAL; 713 /* 714 uint32 lock_source; 715 int32 lock_data; 716 uint32 timecode_source; 717 uint32 * connectors; 718 */ 719 return B_OK; 720 } 721 722 static status_t 723 auich_set_enabled_channels(auich_dev *card, multi_channel_enable *data) 724 { 725 PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data->enable_bits, 0) ? "enabled": "disabled")); 726 PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data->enable_bits, 1) ? "enabled": "disabled")); 727 PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data->enable_bits, 2) ? "enabled": "disabled")); 728 PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data->enable_bits, 3) ? "enabled": "disabled")); 729 return B_OK; 730 } 731 732 static status_t 733 auich_get_global_format(auich_dev *card, multi_format_info *data) 734 { 735 data->output_latency = 0; 736 data->input_latency = 0; 737 data->timecode_kind = 0; 738 data->input.rate = B_SR_48000; 739 data->input.cvsr = 48000; 740 data->input.format = B_FMT_16BIT; 741 data->output.rate = B_SR_48000; 742 data->output.cvsr = 48000; 743 data->output.format = B_FMT_16BIT; 744 /*data->input.rate = B_SR_44100; 745 data->input.cvsr = 44100; 746 data->input.format = B_FMT_16BIT; 747 data->output.rate = B_SR_44100; 748 data->output.cvsr = 44100; 749 data->output.format = B_FMT_16BIT;*/ 750 return B_OK; 751 } 752 753 static status_t 754 auich_get_buffers(auich_dev *card, multi_buffer_list *data) 755 { 756 uint8 i, j, pchannels, rchannels, bufcount; 757 758 LOG(("flags = %#x\n",data->flags)); 759 LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers)); 760 LOG(("request_playback_channels = %#x\n",data->request_playback_channels)); 761 LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size)); 762 LOG(("request_record_buffers = %#x\n",data->request_record_buffers)); 763 LOG(("request_record_channels = %#x\n",data->request_record_channels)); 764 LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size)); 765 766 pchannels = card->pstream->channels; 767 rchannels = card->rstream->channels; 768 769 if (data->request_playback_buffers < current_settings.buffer_count || 770 data->request_playback_channels < (pchannels) || 771 data->request_record_buffers < current_settings.buffer_count || 772 data->request_record_channels < (rchannels)) { 773 LOG(("not enough channels/buffers\n")); 774 } 775 776 ASSERT(current_settings.buffer_count == 2); 777 778 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ??? 779 // data->flags = 0; 780 781 data->return_playback_buffers = current_settings.buffer_count; /* playback_buffers[b][] */ 782 data->return_playback_channels = pchannels; /* playback_buffers[][c] */ 783 data->return_playback_buffer_size = current_settings.buffer_frames; /* frames */ 784 785 bufcount = current_settings.buffer_count; 786 if(bufcount > data->request_playback_buffers) 787 bufcount = data->request_playback_buffers; 788 789 for(i=0; i<bufcount; i++) 790 for(j=0; j<pchannels; j++) 791 auich_stream_get_nth_buffer(card->pstream, j, i, 792 &data->playback_buffers[i][j].base, 793 &data->playback_buffers[i][j].stride); 794 795 data->return_record_buffers = current_settings.buffer_count; 796 data->return_record_channels = rchannels; 797 data->return_record_buffer_size = current_settings.buffer_frames; /* frames */ 798 799 bufcount = current_settings.buffer_count; 800 if(bufcount > data->request_record_buffers) 801 bufcount = data->request_record_buffers; 802 803 for(i=0; i<bufcount; i++) 804 for(j=0; j<rchannels; j++) 805 auich_stream_get_nth_buffer(card->rstream, j, i, 806 &data->record_buffers[i][j].base, 807 &data->record_buffers[i][j].stride); 808 809 return B_OK; 810 } 811 812 813 static void 814 auich_play_inth(void* inthparams) 815 { 816 auich_stream *stream = (auich_stream *)inthparams; 817 //int32 count; 818 819 acquire_spinlock(&slock); 820 stream->real_time = system_time(); 821 stream->frames_count += current_settings.buffer_frames; 822 stream->buffer_cycle = (stream->trigblk 823 + stream->blkmod - 1) % stream->blkmod; 824 stream->update_needed = true; 825 release_spinlock(&slock); 826 827 TRACE(("auich_play_inth : cycle : %d\n", stream->buffer_cycle)); 828 829 //get_sem_count(stream->card->buffer_ready_sem, &count); 830 //if (count <= 0) 831 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 832 } 833 834 static void 835 auich_record_inth(void* inthparams) 836 { 837 auich_stream *stream = (auich_stream *)inthparams; 838 //int32 count; 839 840 acquire_spinlock(&slock); 841 stream->real_time = system_time(); 842 stream->frames_count += current_settings.buffer_frames; 843 stream->buffer_cycle = (stream->trigblk 844 + stream->blkmod - 1) % stream->blkmod; 845 stream->update_needed = true; 846 release_spinlock(&slock); 847 848 TRACE(("auich_record_inth : cycle : %d\n", stream->buffer_cycle)); 849 850 //get_sem_count(stream->card->buffer_ready_sem, &count); 851 //if (count <= 0) 852 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 853 } 854 855 static status_t 856 auich_buffer_exchange(auich_dev *card, multi_buffer_info *data) 857 { 858 cpu_status status; 859 auich_stream *pstream, *rstream; 860 861 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 862 863 if (!(card->pstream->state & AUICH_STATE_STARTED)) 864 auich_stream_start(card->pstream, auich_play_inth, card->pstream); 865 866 if (!(card->rstream->state & AUICH_STATE_STARTED)) 867 auich_stream_start(card->rstream, auich_record_inth, card->rstream); 868 869 if(acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000) 870 == B_TIMED_OUT) { 871 LOG(("buffer_exchange timeout ff\n")); 872 } 873 874 status = lock(); 875 876 LIST_FOREACH(pstream, &card->streams, next) { 877 if ((pstream->use & AUICH_USE_PLAY) == 0 || 878 (pstream->state & AUICH_STATE_STARTED) == 0) 879 continue; 880 if(pstream->update_needed) 881 break; 882 } 883 884 LIST_FOREACH(rstream, &card->streams, next) { 885 if ((rstream->use & AUICH_USE_RECORD) == 0 || 886 (rstream->state & AUICH_STATE_STARTED) == 0) 887 continue; 888 if(rstream->update_needed) 889 break; 890 } 891 892 if(!pstream) 893 pstream = card->pstream; 894 if(!rstream) 895 rstream = card->rstream; 896 897 /* do playback */ 898 data->playback_buffer_cycle = pstream->buffer_cycle; 899 data->played_real_time = pstream->real_time; 900 data->played_frames_count = pstream->frames_count; 901 data->_reserved_0 = pstream->first_channel; 902 pstream->update_needed = false; 903 904 /* do record */ 905 data->record_buffer_cycle = rstream->buffer_cycle; 906 data->recorded_frames_count = rstream->frames_count; 907 data->recorded_real_time = rstream->real_time; 908 data->_reserved_1 = rstream->first_channel; 909 rstream->update_needed = false; 910 unlock(status); 911 912 //TRACE(("buffer_exchange ended\n")); 913 return B_OK; 914 } 915 916 static status_t 917 auich_buffer_force_stop(auich_dev *card) 918 { 919 //auich_voice_halt(card->pvoice); 920 return B_OK; 921 } 922 923 static status_t 924 auich_multi_control(void *cookie, uint32 op, void *data, size_t length) 925 { 926 auich_dev *card = (auich_dev *)cookie; 927 928 switch (op) { 929 case B_MULTI_GET_DESCRIPTION: 930 LOG(("B_MULTI_GET_DESCRIPTION\n")); 931 return auich_get_description(card, (multi_description *)data); 932 case B_MULTI_GET_EVENT_INFO: 933 LOG(("B_MULTI_GET_EVENT_INFO\n")); 934 return B_ERROR; 935 case B_MULTI_SET_EVENT_INFO: 936 LOG(("B_MULTI_SET_EVENT_INFO\n")); 937 return B_ERROR; 938 case B_MULTI_GET_EVENT: 939 LOG(("B_MULTI_GET_EVENT\n")); 940 return B_ERROR; 941 case B_MULTI_GET_ENABLED_CHANNELS: 942 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n")); 943 return auich_get_enabled_channels(card, (multi_channel_enable *)data); 944 case B_MULTI_SET_ENABLED_CHANNELS: 945 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n")); 946 return auich_set_enabled_channels(card, (multi_channel_enable *)data); 947 case B_MULTI_GET_GLOBAL_FORMAT: 948 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n")); 949 return auich_get_global_format(card, (multi_format_info *)data); 950 case B_MULTI_SET_GLOBAL_FORMAT: 951 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n")); 952 return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent 953 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT 954 */ 955 case B_MULTI_GET_CHANNEL_FORMATS: 956 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n")); 957 return B_ERROR; 958 case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */ 959 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n")); 960 return B_ERROR; 961 case B_MULTI_GET_MIX: 962 LOG(("B_MULTI_GET_MIX\n")); 963 return auich_get_mix(card, (multi_mix_value_info *)data); 964 case B_MULTI_SET_MIX: 965 LOG(("B_MULTI_SET_MIX\n")); 966 return auich_set_mix(card, (multi_mix_value_info *)data); 967 case B_MULTI_LIST_MIX_CHANNELS: 968 LOG(("B_MULTI_LIST_MIX_CHANNELS\n")); 969 return auich_list_mix_channels(card, (multi_mix_channel_info *)data); 970 case B_MULTI_LIST_MIX_CONTROLS: 971 LOG(("B_MULTI_LIST_MIX_CONTROLS\n")); 972 return auich_list_mix_controls(card, (multi_mix_control_info *)data); 973 case B_MULTI_LIST_MIX_CONNECTIONS: 974 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n")); 975 return auich_list_mix_connections(card, (multi_mix_connection_info *)data); 976 case B_MULTI_GET_BUFFERS: /* Fill out the struct for the first time; doesn't start anything. */ 977 LOG(("B_MULTI_GET_BUFFERS\n")); 978 return auich_get_buffers(card, data); 979 case B_MULTI_SET_BUFFERS: /* Set what buffers to use, if the driver supports soft buffers. */ 980 LOG(("B_MULTI_SET_BUFFERS\n")); 981 return B_ERROR; /* we do not support soft buffers */ 982 case B_MULTI_SET_START_TIME: /* When to actually start */ 983 LOG(("B_MULTI_SET_START_TIME\n")); 984 return B_ERROR; 985 case B_MULTI_BUFFER_EXCHANGE: /* stop and go are derived from this being called */ 986 //TRACE(("B_MULTI_BUFFER_EXCHANGE\n")); 987 return auich_buffer_exchange(card, (multi_buffer_info *)data); 988 case B_MULTI_BUFFER_FORCE_STOP: /* force stop of playback, nothing in data */ 989 LOG(("B_MULTI_BUFFER_FORCE_STOP\n")); 990 return auich_buffer_force_stop(card); 991 } 992 LOG(("ERROR: unknown multi_control %#x\n",op)); 993 return B_ERROR; 994 } 995 996 static status_t auich_open(const char *name, uint32 flags, void** cookie); 997 static status_t auich_close(void* cookie); 998 static status_t auich_free(void* cookie); 999 static status_t auich_control(void* cookie, uint32 op, void* arg, size_t len); 1000 static status_t auich_read(void* cookie, off_t position, void *buf, size_t* num_bytes); 1001 static status_t auich_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes); 1002 1003 device_hooks multi_hooks = { 1004 auich_open, /* -> open entry point */ 1005 auich_close, /* -> close entry point */ 1006 auich_free, /* -> free cookie */ 1007 auich_control, /* -> control entry point */ 1008 auich_read, /* -> read entry point */ 1009 auich_write, /* -> write entry point */ 1010 NULL, /* start select */ 1011 NULL, /* stop select */ 1012 NULL, /* scatter-gather read from the device */ 1013 NULL /* scatter-gather write to the device */ 1014 }; 1015 1016 static status_t 1017 auich_open(const char *name, uint32 flags, void** cookie) 1018 { 1019 auich_dev *card = NULL; 1020 int ix; 1021 1022 LOG(("open()\n")); 1023 1024 for (ix=0; ix<num_cards; ix++) { 1025 if (!strcmp(cards[ix].name, name)) { 1026 card = &cards[ix]; 1027 } 1028 } 1029 1030 if(card == NULL) { 1031 LOG(("open() card not found %s\n", name)); 1032 for (ix=0; ix<num_cards; ix++) { 1033 LOG(("open() card available %s\n", cards[ix].name)); 1034 } 1035 return B_ERROR; 1036 } 1037 1038 LOG(("open() got card\n")); 1039 1040 if(card->pstream !=NULL) 1041 return B_ERROR; 1042 if(card->rstream !=NULL) 1043 return B_ERROR; 1044 1045 *cookie = card; 1046 card->multi.card = card; 1047 1048 LOG(("stream_new\n")); 1049 1050 card->rstream = auich_stream_new(card, AUICH_USE_RECORD, current_settings.buffer_frames, current_settings.buffer_count); 1051 card->pstream = auich_stream_new(card, AUICH_USE_PLAY, current_settings.buffer_frames, current_settings.buffer_count); 1052 1053 card->buffer_ready_sem = create_sem(0, "pbuffer ready"); 1054 1055 LOG(("stream_setaudio\n")); 1056 1057 auich_stream_set_audioparms(card->pstream, 2, true, current_settings.sample_rate); 1058 auich_stream_set_audioparms(card->rstream, 2, true, current_settings.sample_rate); 1059 1060 card->pstream->first_channel = 0; 1061 card->rstream->first_channel = 2; 1062 1063 auich_stream_commit_parms(card->pstream); 1064 auich_stream_commit_parms(card->rstream); 1065 1066 auich_create_channels_list(&card->multi); 1067 1068 return B_OK; 1069 } 1070 1071 static status_t 1072 auich_close(void* cookie) 1073 { 1074 //auich_dev *card = cookie; 1075 LOG(("close()\n")); 1076 1077 return B_OK; 1078 } 1079 1080 static status_t 1081 auich_free(void* cookie) 1082 { 1083 auich_dev *card = cookie; 1084 auich_stream *stream; 1085 LOG(("free()\n")); 1086 1087 if (card->buffer_ready_sem > B_OK) 1088 delete_sem(card->buffer_ready_sem); 1089 1090 LIST_FOREACH(stream, &card->streams, next) { 1091 auich_stream_halt(stream); 1092 } 1093 1094 while(!LIST_EMPTY(&card->streams)) { 1095 auich_stream_delete(LIST_FIRST(&card->streams)); 1096 } 1097 1098 return B_OK; 1099 } 1100 1101 static status_t 1102 auich_control(void* cookie, uint32 op, void* arg, size_t len) 1103 { 1104 return auich_multi_control(cookie, op, arg, len); 1105 } 1106 1107 static status_t 1108 auich_read(void* cookie, off_t position, void *buf, size_t* num_bytes) 1109 { 1110 *num_bytes = 0; /* tell caller nothing was read */ 1111 return B_IO_ERROR; 1112 } 1113 1114 static status_t 1115 auich_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) 1116 { 1117 *num_bytes = 0; /* tell caller nothing was written */ 1118 return B_IO_ERROR; 1119 } 1120 1121