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