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