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, uint32* index, int32 parent, int32 string, 180 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 194 return multi->controls[i].mix_control.id; 195 } 196 197 198 static status_t 199 auvia_create_controls_list(multi_dev *multi) 200 { 201 uint32 i = 0, index = 0, count, id, parent, parent2, parent3; 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 %" B_PRIu32 "\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 || (uint32)id >= card->multi.control_count) { 406 PRINT(("auvia_get_mix : " 407 "invalid control id requested : %" B_PRIi32 "\n", id)); 408 continue; 409 } 410 control = &card->multi.controls[id]; 411 412 if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 413 if (control->get) { 414 float values[2]; 415 control->get(card, control->cookie, control->type, values); 416 if (control->mix_control.master == EMU_MULTI_CONTROL_MASTERID) 417 mmvi->values[i].u.gain = values[0]; 418 else 419 mmvi->values[i].u.gain = values[1]; 420 } 421 } 422 423 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) { 424 float values[1]; 425 control->get(card, control->cookie, control->type, values); 426 mmvi->values[i].u.enable = (values[0] == 1.0); 427 } 428 429 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) { 430 float values[1]; 431 control->get(card, control->cookie, control->type, values); 432 mmvi->values[i].u.mux = (int32)values[0]; 433 } 434 } 435 return B_OK; 436 } 437 438 439 static status_t 440 auvia_set_mix(auvia_dev *card, multi_mix_value_info * mmvi) 441 { 442 int32 i, id; 443 multi_mixer_control *control = NULL; 444 for (i = 0; i < mmvi->item_count; i++) { 445 id = mmvi->values[i].id - EMU_MULTI_CONTROL_FIRSTID; 446 if (id < 0 || (uint32)id >= card->multi.control_count) { 447 PRINT(("auvia_set_mix : " 448 "invalid control id requested : %" B_PRIi32 "\n", id)); 449 continue; 450 } 451 control = &card->multi.controls[id]; 452 453 if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 454 multi_mixer_control *control2 = NULL; 455 if (i + 1 < mmvi->item_count) { 456 id = mmvi->values[i + 1].id - EMU_MULTI_CONTROL_FIRSTID; 457 if (id < 0 || (uint32)id >= card->multi.control_count) { 458 PRINT(("auvia_set_mix : " 459 "invalid control id requested : %" B_PRIi32 "\n", id)); 460 } else { 461 control2 = &card->multi.controls[id]; 462 if (control2->mix_control.master != control->mix_control.id) 463 control2 = NULL; 464 } 465 } 466 467 if (control->set) { 468 float values[2]; 469 values[0] = 0.0; 470 values[1] = 0.0; 471 472 if (control->mix_control.master == EMU_MULTI_CONTROL_MASTERID) 473 values[0] = mmvi->values[i].u.gain; 474 else 475 values[1] = mmvi->values[i].u.gain; 476 477 if (control2 && control2->mix_control.master != EMU_MULTI_CONTROL_MASTERID) 478 values[1] = mmvi->values[i + 1].u.gain; 479 480 control->set(card, control->cookie, control->type, values); 481 } 482 483 if (control2) 484 i++; 485 } 486 487 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) { 488 float values[1]; 489 490 values[0] = mmvi->values[i].u.enable ? 1.0 : 0.0; 491 control->set(card, control->cookie, control->type, values); 492 } 493 494 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) { 495 float values[1]; 496 497 values[0] = (float)mmvi->values[i].u.mux; 498 control->set(card, control->cookie, control->type, values); 499 } 500 } 501 return B_OK; 502 } 503 504 505 static status_t 506 auvia_list_mix_controls(auvia_dev *card, multi_mix_control_info * mmci) 507 { 508 multi_mix_control *mmc; 509 uint32 i; 510 511 mmc = mmci->controls; 512 if (mmci->control_count < 24) 513 return B_ERROR; 514 515 if (auvia_create_controls_list(&card->multi) < B_OK) 516 return B_ERROR; 517 for (i = 0; i < card->multi.control_count; i++) { 518 mmc[i] = card->multi.controls[i].mix_control; 519 } 520 521 mmci->control_count = card->multi.control_count; 522 return B_OK; 523 } 524 525 526 static status_t 527 auvia_list_mix_connections(auvia_dev *card, multi_mix_connection_info * data) 528 { 529 return B_ERROR; 530 } 531 532 533 static status_t 534 auvia_list_mix_channels(auvia_dev *card, multi_mix_channel_info *data) 535 { 536 return B_ERROR; 537 } 538 539 /*multi_channel_info chans[] = { 540 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 541 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 542 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 543 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 544 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 545 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 546 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 547 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 548 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 549 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 550 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 551 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 552 };*/ 553 554 /*multi_channel_info chans[] = { 555 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 556 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 557 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 }, 558 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 }, 559 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 }, 560 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 }, 561 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 562 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 563 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 564 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 565 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 566 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 567 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 568 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 569 };*/ 570 571 572 static void 573 auvia_create_channels_list(multi_dev *multi) 574 { 575 auvia_stream *stream; 576 uint32 index, i, designations; 577 int32 mode; 578 multi_channel_info *chans; 579 uint32 chan_designations[] = { 580 B_CHANNEL_LEFT, 581 B_CHANNEL_RIGHT, 582 B_CHANNEL_REARLEFT, 583 B_CHANNEL_REARRIGHT, 584 B_CHANNEL_CENTER, 585 B_CHANNEL_SUB 586 }; 587 588 chans = multi->chans; 589 index = 0; 590 591 for (mode = AUVIA_USE_PLAY; mode != -1; 592 mode = (mode == AUVIA_USE_PLAY) ? AUVIA_USE_RECORD : -1) { 593 LIST_FOREACH(stream, &((auvia_dev*)multi->card)->streams, next) { 594 if ((stream->use & mode) == 0) 595 continue; 596 597 if (stream->channels == 2) 598 designations = B_CHANNEL_STEREO_BUS; 599 else 600 designations = B_CHANNEL_SURROUND_BUS; 601 602 for (i = 0; i < stream->channels; i++) { 603 chans[index].channel_id = index; 604 chans[index].kind = 605 (mode == AUVIA_USE_PLAY) ? B_MULTI_OUTPUT_CHANNEL : B_MULTI_INPUT_CHANNEL; 606 chans[index].designations = designations | chan_designations[i]; 607 chans[index].connectors = 0; 608 index++; 609 } 610 } 611 612 if (mode == AUVIA_USE_PLAY) { 613 multi->output_channel_count = index; 614 } else { 615 multi->input_channel_count = index - multi->output_channel_count; 616 } 617 } 618 619 chans[index].channel_id = index; 620 chans[index].kind = B_MULTI_OUTPUT_BUS; 621 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS; 622 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 623 index++; 624 625 chans[index].channel_id = index; 626 chans[index].kind = B_MULTI_OUTPUT_BUS; 627 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS; 628 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 629 index++; 630 631 multi->output_bus_channel_count = index - multi->output_channel_count 632 - multi->input_channel_count; 633 634 chans[index].channel_id = index; 635 chans[index].kind = B_MULTI_INPUT_BUS; 636 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS; 637 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 638 index++; 639 640 chans[index].channel_id = index; 641 chans[index].kind = B_MULTI_INPUT_BUS; 642 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS; 643 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO; 644 index++; 645 646 multi->input_bus_channel_count = index - multi->output_channel_count 647 - multi->input_channel_count - multi->output_bus_channel_count; 648 649 multi->aux_bus_channel_count = 0; 650 } 651 652 653 static status_t 654 auvia_get_description(auvia_dev *card, multi_description *data) 655 { 656 uint32 size; 657 658 data->interface_version = B_CURRENT_INTERFACE_VERSION; 659 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 660 661 if (IS_686(&card->config)) 662 strncpy(data->friendly_name, FRIENDLY_NAME_686, 32); 663 else if (IS_8233(&card->config)) { 664 switch (card->info.revision) { 665 case VIATECH_8233_AC97_REV_8233_10: 666 strncpy(data->friendly_name, FRIENDLY_NAME_8233, 32); 667 break; 668 case VIATECH_8233_AC97_REV_8233C: 669 strncpy(data->friendly_name, FRIENDLY_NAME_8233C, 32); 670 break; 671 case VIATECH_8233_AC97_REV_8233: 672 strncpy(data->friendly_name, FRIENDLY_NAME_8233, 32); 673 break; 674 case VIATECH_8233_AC97_REV_8233A: 675 strncpy(data->friendly_name, FRIENDLY_NAME_8233A, 32); 676 break; 677 case VIATECH_8233_AC97_REV_8235: 678 strncpy(data->friendly_name, FRIENDLY_NAME_8235, 32); 679 break; 680 case VIATECH_8233_AC97_REV_8237: 681 strncpy(data->friendly_name, FRIENDLY_NAME_8237, 32); 682 break; 683 default: 684 strncpy(data->friendly_name, FRIENDLY_NAME, 32); 685 } 686 } 687 strcpy(data->vendor_info, AUTHOR); 688 689 /*data->output_channel_count = 6; 690 data->input_channel_count = 4; 691 data->output_bus_channel_count = 2; 692 data->input_bus_channel_count = 2; 693 data->aux_bus_channel_count = 0;*/ 694 695 data->output_channel_count = card->multi.output_channel_count; 696 data->input_channel_count = card->multi.input_channel_count; 697 data->output_bus_channel_count = card->multi.output_bus_channel_count; 698 data->input_bus_channel_count = card->multi.input_bus_channel_count; 699 data->aux_bus_channel_count = card->multi.aux_bus_channel_count; 700 701 size = card->multi.output_channel_count + card->multi.input_channel_count 702 + card->multi.output_bus_channel_count + card->multi.input_bus_channel_count 703 + card->multi.aux_bus_channel_count; 704 705 // for each channel, starting with the first output channel, 706 // then the second, third..., followed by the first input 707 // channel, second, third, ..., followed by output bus 708 // channels and input bus channels and finally auxillary channels, 709 710 LOG(("request_channel_count = %d\n",data->request_channel_count)); 711 if (data->request_channel_count >= (int32)size) { 712 LOG(("copying data\n")); 713 memcpy(data->channels, card->multi.chans, size * sizeof(card->multi.chans[0])); 714 } 715 716 data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR; 717 data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR; 718 //data->output_rates = B_SR_44100; 719 //data->input_rates = B_SR_44100; 720 data->min_cvsr_rate = 0; 721 data->max_cvsr_rate = 48000; 722 //data->max_cvsr_rate = 44100; 723 724 data->output_formats = B_FMT_16BIT; 725 data->input_formats = B_FMT_16BIT; 726 data->lock_sources = B_MULTI_LOCK_INTERNAL; 727 data->timecode_sources = 0; 728 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 729 data->start_latency = 3000; 730 731 strcpy(data->control_panel, ""); 732 733 return B_OK; 734 } 735 736 737 static status_t 738 auvia_get_enabled_channels(auvia_dev *card, multi_channel_enable *data) 739 { 740 B_SET_CHANNEL(data->enable_bits, 0, true); 741 B_SET_CHANNEL(data->enable_bits, 1, true); 742 B_SET_CHANNEL(data->enable_bits, 2, true); 743 B_SET_CHANNEL(data->enable_bits, 3, true); 744 data->lock_source = B_MULTI_LOCK_INTERNAL; 745 /* 746 uint32 lock_source; 747 int32 lock_data; 748 uint32 timecode_source; 749 uint32 * connectors; 750 */ 751 return B_OK; 752 } 753 754 755 static status_t 756 auvia_set_enabled_channels(auvia_dev *card, multi_channel_enable *data) 757 { 758 PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data->enable_bits, 0) ? "enabled": "disabled")); 759 PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data->enable_bits, 1) ? "enabled": "disabled")); 760 PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data->enable_bits, 2) ? "enabled": "disabled")); 761 PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data->enable_bits, 3) ? "enabled": "disabled")); 762 return B_OK; 763 } 764 765 766 static status_t 767 auvia_get_global_format(auvia_dev *card, multi_format_info *data) 768 { 769 data->output_latency = 0; 770 data->input_latency = 0; 771 data->timecode_kind = 0; 772 data->input.rate = B_SR_48000; 773 data->input.cvsr = 48000; 774 data->input.format = B_FMT_16BIT; 775 data->output.rate = B_SR_48000; 776 data->output.cvsr = 48000; 777 data->output.format = B_FMT_16BIT; 778 /*data->input.rate = B_SR_44100; 779 data->input.cvsr = 44100; 780 data->input.format = B_FMT_16BIT; 781 data->output.rate = B_SR_44100; 782 data->output.cvsr = 44100; 783 data->output.format = B_FMT_16BIT;*/ 784 return B_OK; 785 } 786 787 788 static status_t 789 auvia_get_buffers(auvia_dev *card, multi_buffer_list *data) 790 { 791 uint32 i, j, pchannels, rchannels; 792 793 LOG(("flags = %#x\n",data->flags)); 794 LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers)); 795 LOG(("request_playback_channels = %#x\n",data->request_playback_channels)); 796 LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size)); 797 LOG(("request_record_buffers = %#x\n",data->request_record_buffers)); 798 LOG(("request_record_channels = %#x\n",data->request_record_channels)); 799 LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size)); 800 801 pchannels = card->pstream->channels; 802 rchannels = card->rstream->channels; 803 804 if (data->request_playback_buffers < BUFFER_COUNT 805 || data->request_playback_channels < (int32)(pchannels) 806 || data->request_record_buffers < BUFFER_COUNT 807 || data->request_record_channels < (int32)(rchannels)) { 808 LOG(("not enough channels/buffers\n")); 809 } 810 811 ASSERT(BUFFER_COUNT == 2); 812 813 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ??? 814 // data->flags = 0; 815 816 data->return_playback_buffers = BUFFER_COUNT; /* playback_buffers[b][] */ 817 data->return_playback_channels = pchannels; /* playback_buffers[][c] */ 818 data->return_playback_buffer_size = BUFFER_FRAMES; /* frames */ 819 820 for (i = 0; i < BUFFER_COUNT; i++) 821 for (j = 0; j < pchannels; j++) 822 auvia_stream_get_nth_buffer(card->pstream, j, i, 823 &data->playback_buffers[i][j].base, 824 &data->playback_buffers[i][j].stride); 825 826 data->return_record_buffers = BUFFER_COUNT; 827 data->return_record_channels = rchannels; 828 data->return_record_buffer_size = BUFFER_FRAMES; /* frames */ 829 830 for (i = 0; i < BUFFER_COUNT; i++) 831 for (j = 0; j<rchannels; j++) 832 auvia_stream_get_nth_buffer(card->rstream, j, i, 833 &data->record_buffers[i][j].base, 834 &data->record_buffers[i][j].stride); 835 836 return B_OK; 837 } 838 839 840 static void 841 auvia_play_inth(void* inthparams) 842 { 843 auvia_stream *stream = (auvia_stream *)inthparams; 844 //int32 count; 845 846 //TRACE(("auvia_play_inth\n")); 847 848 acquire_spinlock(&slock); 849 stream->real_time = system_time(); 850 stream->frames_count += BUFFER_FRAMES; 851 stream->buffer_cycle = (stream->trigblk 852 + stream->blkmod - 1) % stream->blkmod; 853 stream->update_needed = true; 854 release_spinlock(&slock); 855 856 //get_sem_count(stream->card->buffer_ready_sem, &count); 857 //if (count <= 0) 858 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 859 } 860 861 862 static void 863 auvia_record_inth(void* inthparams) 864 { 865 auvia_stream *stream = (auvia_stream *)inthparams; 866 //int32 count; 867 868 //TRACE(("auvia_record_inth\n")); 869 870 acquire_spinlock(&slock); 871 stream->real_time = system_time(); 872 stream->frames_count += BUFFER_FRAMES; 873 stream->buffer_cycle = (stream->trigblk 874 + stream->blkmod - 1) % stream->blkmod; 875 stream->update_needed = true; 876 release_spinlock(&slock); 877 878 //get_sem_count(stream->card->buffer_ready_sem, &count); 879 //if (count <= 0) 880 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 881 } 882 883 884 static status_t 885 auvia_buffer_exchange(auvia_dev *card, multi_buffer_info *data) 886 { 887 cpu_status status; 888 auvia_stream *pstream, *rstream; 889 multi_buffer_info buffer_info; 890 891 #ifdef __HAIKU__ 892 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) 893 return B_BAD_ADDRESS; 894 #else 895 memcpy(&buffer_info, data, sizeof(buffer_info)); 896 #endif 897 898 buffer_info.flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 899 900 if (!(card->pstream->state & AUVIA_STATE_STARTED)) 901 auvia_stream_start(card->pstream, auvia_play_inth, card->pstream); 902 903 if (!(card->rstream->state & AUVIA_STATE_STARTED)) 904 auvia_stream_start(card->rstream, auvia_record_inth, card->rstream); 905 906 if (acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000) 907 == B_TIMED_OUT) { 908 LOG(("buffer_exchange timeout ff\n")); 909 } 910 911 status = lock(); 912 913 LIST_FOREACH(pstream, &card->streams, next) { 914 if ((pstream->use & AUVIA_USE_PLAY) == 0 || 915 (pstream->state & AUVIA_STATE_STARTED) == 0) 916 continue; 917 if (pstream->update_needed) 918 break; 919 } 920 921 LIST_FOREACH(rstream, &card->streams, next) { 922 if ((rstream->use & AUVIA_USE_RECORD) == 0 || 923 (rstream->state & AUVIA_STATE_STARTED) == 0) 924 continue; 925 if (rstream->update_needed) 926 break; 927 } 928 929 if (!pstream) 930 pstream = card->pstream; 931 if (!rstream) 932 rstream = card->rstream; 933 934 /* do playback */ 935 buffer_info.playback_buffer_cycle = pstream->buffer_cycle; 936 buffer_info.played_real_time = pstream->real_time; 937 buffer_info.played_frames_count = pstream->frames_count; 938 buffer_info._reserved_0 = pstream->first_channel; 939 pstream->update_needed = false; 940 941 /* do record */ 942 buffer_info.record_buffer_cycle = rstream->buffer_cycle; 943 buffer_info.recorded_frames_count = rstream->frames_count; 944 buffer_info.recorded_real_time = rstream->real_time; 945 buffer_info._reserved_1 = rstream->first_channel; 946 rstream->update_needed = false; 947 unlock(status); 948 949 #ifdef __HAIKU__ 950 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) 951 return B_BAD_ADDRESS; 952 #else 953 memcpy(data, &buffer_info, sizeof(buffer_info)); 954 #endif 955 956 //TRACE(("buffer_exchange ended\n")); 957 return B_OK; 958 } 959 960 961 static status_t 962 auvia_buffer_force_stop(auvia_dev *card) 963 { 964 //auvia_voice_halt(card->pvoice); 965 return B_OK; 966 } 967 968 969 static status_t 970 auvia_multi_control(void *cookie, uint32 op, void *data, size_t length) 971 { 972 auvia_dev *card = (auvia_dev *)cookie; 973 974 switch (op) { 975 case B_MULTI_GET_DESCRIPTION: 976 LOG(("B_MULTI_GET_DESCRIPTION\n")); 977 return auvia_get_description(card, (multi_description *)data); 978 case B_MULTI_GET_EVENT_INFO: 979 LOG(("B_MULTI_GET_EVENT_INFO\n")); 980 return B_ERROR; 981 case B_MULTI_SET_EVENT_INFO: 982 LOG(("B_MULTI_SET_EVENT_INFO\n")); 983 return B_ERROR; 984 case B_MULTI_GET_EVENT: 985 LOG(("B_MULTI_GET_EVENT\n")); 986 return B_ERROR; 987 case B_MULTI_GET_ENABLED_CHANNELS: 988 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n")); 989 return auvia_get_enabled_channels(card, (multi_channel_enable *)data); 990 case B_MULTI_SET_ENABLED_CHANNELS: 991 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n")); 992 return auvia_set_enabled_channels(card, (multi_channel_enable *)data); 993 case B_MULTI_GET_GLOBAL_FORMAT: 994 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n")); 995 return auvia_get_global_format(card, (multi_format_info *)data); 996 case B_MULTI_SET_GLOBAL_FORMAT: 997 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n")); 998 return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent 999 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT 1000 */ 1001 case B_MULTI_GET_CHANNEL_FORMATS: 1002 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n")); 1003 return B_ERROR; 1004 case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */ 1005 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n")); 1006 return B_ERROR; 1007 case B_MULTI_GET_MIX: 1008 LOG(("B_MULTI_GET_MIX\n")); 1009 return auvia_get_mix(card, (multi_mix_value_info *)data); 1010 case B_MULTI_SET_MIX: 1011 LOG(("B_MULTI_SET_MIX\n")); 1012 return auvia_set_mix(card, (multi_mix_value_info *)data); 1013 case B_MULTI_LIST_MIX_CHANNELS: 1014 LOG(("B_MULTI_LIST_MIX_CHANNELS\n")); 1015 return auvia_list_mix_channels(card, (multi_mix_channel_info *)data); 1016 case B_MULTI_LIST_MIX_CONTROLS: 1017 LOG(("B_MULTI_LIST_MIX_CONTROLS\n")); 1018 return auvia_list_mix_controls(card, (multi_mix_control_info *)data); 1019 case B_MULTI_LIST_MIX_CONNECTIONS: 1020 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n")); 1021 return auvia_list_mix_connections(card, (multi_mix_connection_info *)data); 1022 case B_MULTI_GET_BUFFERS: /* Fill out the struct for the first time; doesn't start anything. */ 1023 LOG(("B_MULTI_GET_BUFFERS\n")); 1024 return auvia_get_buffers(card, data); 1025 case B_MULTI_SET_BUFFERS: /* Set what buffers to use, if the driver supports soft buffers. */ 1026 LOG(("B_MULTI_SET_BUFFERS\n")); 1027 return B_ERROR; /* we do not support soft buffers */ 1028 case B_MULTI_SET_START_TIME: /* When to actually start */ 1029 LOG(("B_MULTI_SET_START_TIME\n")); 1030 return B_ERROR; 1031 case B_MULTI_BUFFER_EXCHANGE: /* stop and go are derived from this being called */ 1032 //TRACE(("B_MULTI_BUFFER_EXCHANGE\n")); 1033 return auvia_buffer_exchange(card, (multi_buffer_info *)data); 1034 case B_MULTI_BUFFER_FORCE_STOP: /* force stop of playback, nothing in data */ 1035 LOG(("B_MULTI_BUFFER_FORCE_STOP\n")); 1036 return auvia_buffer_force_stop(card); 1037 } 1038 LOG(("ERROR: unknown multi_control %#x\n",op)); 1039 return B_ERROR; 1040 } 1041 1042 static status_t auvia_open(const char *name, uint32 flags, void** cookie); 1043 static status_t auvia_close(void* cookie); 1044 static status_t auvia_free(void* cookie); 1045 static status_t auvia_control(void* cookie, uint32 op, void* arg, size_t len); 1046 static status_t auvia_read(void* cookie, off_t position, void *buf, size_t* num_bytes); 1047 static status_t auvia_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes); 1048 1049 device_hooks multi_hooks = { 1050 auvia_open, /* -> open entry point */ 1051 auvia_close, /* -> close entry point */ 1052 auvia_free, /* -> free cookie */ 1053 auvia_control, /* -> control entry point */ 1054 auvia_read, /* -> read entry point */ 1055 auvia_write, /* -> write entry point */ 1056 NULL, /* start select */ 1057 NULL, /* stop select */ 1058 NULL, /* scatter-gather read from the device */ 1059 NULL /* scatter-gather write to the device */ 1060 }; 1061 1062 1063 static status_t 1064 auvia_open(const char *name, uint32 flags, void** cookie) 1065 { 1066 auvia_dev *card = NULL; 1067 int ix; 1068 1069 LOG(("open()\n")); 1070 1071 for (ix=0; ix<num_cards; ix++) { 1072 if (!strcmp(cards[ix].name, name)) { 1073 card = &cards[ix]; 1074 } 1075 } 1076 1077 if (card == NULL) { 1078 LOG(("open() card not found %s\n", name)); 1079 for (ix=0; ix<num_cards; ix++) { 1080 LOG(("open() card available %s\n", cards[ix].name)); 1081 } 1082 return B_ERROR; 1083 } 1084 1085 LOG(("open() got card\n")); 1086 1087 if (card->pstream !=NULL) 1088 return B_ERROR; 1089 if (card->rstream !=NULL) 1090 return B_ERROR; 1091 1092 *cookie = card; 1093 card->multi.card = card; 1094 1095 LOG(("stream_new\n")); 1096 1097 card->rstream = auvia_stream_new(card, AUVIA_USE_RECORD, BUFFER_FRAMES, BUFFER_COUNT); 1098 card->pstream = auvia_stream_new(card, AUVIA_USE_PLAY, BUFFER_FRAMES, BUFFER_COUNT); 1099 1100 card->buffer_ready_sem = create_sem(0, "pbuffer ready"); 1101 1102 LOG(("stream_setaudio\n")); 1103 1104 auvia_stream_set_audioparms(card->pstream, 2, true, 48000); 1105 auvia_stream_set_audioparms(card->rstream, 2, true, 48000); 1106 1107 card->pstream->first_channel = 0; 1108 card->rstream->first_channel = 2; 1109 1110 auvia_stream_commit_parms(card->pstream); 1111 auvia_stream_commit_parms(card->rstream); 1112 1113 auvia_create_channels_list(&card->multi); 1114 1115 return B_OK; 1116 } 1117 1118 1119 static status_t 1120 auvia_close(void* cookie) 1121 { 1122 //auvia_dev *card = cookie; 1123 LOG(("close()\n")); 1124 1125 return B_OK; 1126 } 1127 1128 1129 static status_t 1130 auvia_free(void* cookie) 1131 { 1132 auvia_dev *card = cookie; 1133 auvia_stream *stream; 1134 LOG(("free()\n")); 1135 1136 if (card->buffer_ready_sem > B_OK) 1137 delete_sem(card->buffer_ready_sem); 1138 1139 LIST_FOREACH(stream, &card->streams, next) { 1140 auvia_stream_halt(stream); 1141 } 1142 1143 while (!LIST_EMPTY(&card->streams)) { 1144 auvia_stream_delete(LIST_FIRST(&card->streams)); 1145 } 1146 1147 card->pstream = NULL; 1148 card->rstream = NULL; 1149 1150 return B_OK; 1151 } 1152 1153 1154 static status_t 1155 auvia_control(void* cookie, uint32 op, void* arg, size_t len) 1156 { 1157 return auvia_multi_control(cookie, op, arg, len); 1158 } 1159 1160 1161 static status_t 1162 auvia_read(void* cookie, off_t position, void *buf, size_t* num_bytes) 1163 { 1164 *num_bytes = 0; /* tell caller nothing was read */ 1165 return B_IO_ERROR; 1166 } 1167 1168 1169 static status_t 1170 auvia_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) 1171 { 1172 *num_bytes = 0; /* tell caller nothing was written */ 1173 return B_IO_ERROR; 1174 } 1175