1 /* 2 * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si> 3 * Takashi Iwai <tiwai@suse.de> 4 * 5 * SB16ASP/AWE32 CSP control 6 * 7 * CSP microcode loader: 8 * alsa-tools/sb16_csp/ 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 */ 25 26 #include <sound/driver.h> 27 #include <linux/delay.h> 28 #include <linux/init.h> 29 #include <linux/slab.h> 30 #include <sound/core.h> 31 #include <sound/control.h> 32 #include <sound/info.h> 33 #include <sound/sb16_csp.h> 34 #include <sound/initval.h> 35 36 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); 37 MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor"); 38 MODULE_LICENSE("GPL"); 39 40 #ifdef SNDRV_LITTLE_ENDIAN 41 #define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) 42 #else 43 #define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24)) 44 #endif 45 46 #define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F') 47 #define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ') 48 #define LIST_HEADER CSP_HDR_VALUE('L', 'I', 'S', 'T') 49 #define FUNC_HEADER CSP_HDR_VALUE('f', 'u', 'n', 'c') 50 #define CODE_HEADER CSP_HDR_VALUE('c', 'o', 'd', 'e') 51 #define INIT_HEADER CSP_HDR_VALUE('i', 'n', 'i', 't') 52 #define MAIN_HEADER CSP_HDR_VALUE('m', 'a', 'i', 'n') 53 54 /* 55 * RIFF data format 56 */ 57 struct riff_header { 58 __u32 name; 59 __u32 len; 60 }; 61 62 struct desc_header { 63 struct riff_header info; 64 __u16 func_nr; 65 __u16 VOC_type; 66 __u16 flags_play_rec; 67 __u16 flags_16bit_8bit; 68 __u16 flags_stereo_mono; 69 __u16 flags_rates; 70 }; 71 72 /* 73 * prototypes 74 */ 75 static void snd_sb_csp_free(struct snd_hwdep *hw); 76 static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file); 77 static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg); 78 static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file); 79 80 static int csp_detect(struct snd_sb *chip, int *version); 81 static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val); 82 static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val); 83 static int read_register(struct snd_sb *chip, unsigned char reg); 84 static int set_mode_register(struct snd_sb *chip, unsigned char mode); 85 static int get_version(struct snd_sb *chip); 86 87 static int snd_sb_csp_riff_load(struct snd_sb_csp * p, 88 struct snd_sb_csp_microcode __user * code); 89 static int snd_sb_csp_unload(struct snd_sb_csp * p); 90 static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags); 91 static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode); 92 static int snd_sb_csp_check_version(struct snd_sb_csp * p); 93 94 static int snd_sb_csp_use(struct snd_sb_csp * p); 95 static int snd_sb_csp_unuse(struct snd_sb_csp * p); 96 static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels); 97 static int snd_sb_csp_stop(struct snd_sb_csp * p); 98 static int snd_sb_csp_pause(struct snd_sb_csp * p); 99 static int snd_sb_csp_restart(struct snd_sb_csp * p); 100 101 static int snd_sb_qsound_build(struct snd_sb_csp * p); 102 static void snd_sb_qsound_destroy(struct snd_sb_csp * p); 103 static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p); 104 105 static int init_proc_entry(struct snd_sb_csp * p, int device); 106 static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); 107 108 /* 109 * Detect CSP chip and create a new instance 110 */ 111 int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) 112 { 113 struct snd_sb_csp *p; 114 int version, err; 115 struct snd_hwdep *hw; 116 117 if (rhwdep) 118 *rhwdep = NULL; 119 120 if (csp_detect(chip, &version)) 121 return -ENODEV; 122 123 if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0) 124 return err; 125 126 if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { 127 snd_device_free(chip->card, hw); 128 return -ENOMEM; 129 } 130 p->chip = chip; 131 p->version = version; 132 133 /* CSP operators */ 134 p->ops.csp_use = snd_sb_csp_use; 135 p->ops.csp_unuse = snd_sb_csp_unuse; 136 p->ops.csp_autoload = snd_sb_csp_autoload; 137 p->ops.csp_start = snd_sb_csp_start; 138 p->ops.csp_stop = snd_sb_csp_stop; 139 p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer; 140 141 mutex_init(&p->access_mutex); 142 sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f)); 143 hw->iface = SNDRV_HWDEP_IFACE_SB16CSP; 144 hw->private_data = p; 145 hw->private_free = snd_sb_csp_free; 146 147 /* operators - only write/ioctl */ 148 hw->ops.open = snd_sb_csp_open; 149 hw->ops.ioctl = snd_sb_csp_ioctl; 150 hw->ops.release = snd_sb_csp_release; 151 152 /* create a proc entry */ 153 init_proc_entry(p, device); 154 if (rhwdep) 155 *rhwdep = hw; 156 return 0; 157 } 158 159 /* 160 * free_private for hwdep instance 161 */ 162 static void snd_sb_csp_free(struct snd_hwdep *hwdep) 163 { 164 #ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL 165 int i; 166 #endif 167 struct snd_sb_csp *p = hwdep->private_data; 168 if (p) { 169 if (p->running & SNDRV_SB_CSP_ST_RUNNING) 170 snd_sb_csp_stop(p); 171 #ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL 172 for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i) 173 release_firmware(p->csp_programs[i]); 174 #endif 175 kfree(p); 176 } 177 } 178 179 /* ------------------------------ */ 180 181 /* 182 * open the device exclusively 183 */ 184 static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file) 185 { 186 struct snd_sb_csp *p = hw->private_data; 187 return (snd_sb_csp_use(p)); 188 } 189 190 /* 191 * ioctl for hwdep device: 192 */ 193 static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) 194 { 195 struct snd_sb_csp *p = hw->private_data; 196 struct snd_sb_csp_info info; 197 struct snd_sb_csp_start start_info; 198 int err; 199 200 snd_assert(p != NULL, return -EINVAL); 201 202 if (snd_sb_csp_check_version(p)) 203 return -ENODEV; 204 205 switch (cmd) { 206 /* get information */ 207 case SNDRV_SB_CSP_IOCTL_INFO: 208 *info.codec_name = *p->codec_name; 209 info.func_nr = p->func_nr; 210 info.acc_format = p->acc_format; 211 info.acc_channels = p->acc_channels; 212 info.acc_width = p->acc_width; 213 info.acc_rates = p->acc_rates; 214 info.csp_mode = p->mode; 215 info.run_channels = p->run_channels; 216 info.run_width = p->run_width; 217 info.version = p->version; 218 info.state = p->running; 219 if (copy_to_user((void __user *)arg, &info, sizeof(info))) 220 err = -EFAULT; 221 else 222 err = 0; 223 break; 224 225 /* load CSP microcode */ 226 case SNDRV_SB_CSP_IOCTL_LOAD_CODE: 227 err = (p->running & SNDRV_SB_CSP_ST_RUNNING ? 228 -EBUSY : snd_sb_csp_riff_load(p, (struct snd_sb_csp_microcode __user *) arg)); 229 break; 230 case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE: 231 err = (p->running & SNDRV_SB_CSP_ST_RUNNING ? 232 -EBUSY : snd_sb_csp_unload(p)); 233 break; 234 235 /* change CSP running state */ 236 case SNDRV_SB_CSP_IOCTL_START: 237 if (copy_from_user(&start_info, (void __user *) arg, sizeof(start_info))) 238 err = -EFAULT; 239 else 240 err = snd_sb_csp_start(p, start_info.sample_width, start_info.channels); 241 break; 242 case SNDRV_SB_CSP_IOCTL_STOP: 243 err = snd_sb_csp_stop(p); 244 break; 245 case SNDRV_SB_CSP_IOCTL_PAUSE: 246 err = snd_sb_csp_pause(p); 247 break; 248 case SNDRV_SB_CSP_IOCTL_RESTART: 249 err = snd_sb_csp_restart(p); 250 break; 251 default: 252 err = -ENOTTY; 253 break; 254 } 255 256 return err; 257 } 258 259 /* 260 * close the device 261 */ 262 static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file) 263 { 264 struct snd_sb_csp *p = hw->private_data; 265 return (snd_sb_csp_unuse(p)); 266 } 267 268 /* ------------------------------ */ 269 270 /* 271 * acquire device 272 */ 273 static int snd_sb_csp_use(struct snd_sb_csp * p) 274 { 275 mutex_lock(&p->access_mutex); 276 if (p->used) { 277 mutex_unlock(&p->access_mutex); 278 return -EAGAIN; 279 } 280 p->used++; 281 mutex_unlock(&p->access_mutex); 282 283 return 0; 284 285 } 286 287 /* 288 * release device 289 */ 290 static int snd_sb_csp_unuse(struct snd_sb_csp * p) 291 { 292 mutex_lock(&p->access_mutex); 293 p->used--; 294 mutex_unlock(&p->access_mutex); 295 296 return 0; 297 } 298 299 /* 300 * load microcode via ioctl: 301 * code is user-space pointer 302 */ 303 static int snd_sb_csp_riff_load(struct snd_sb_csp * p, 304 struct snd_sb_csp_microcode __user * mcode) 305 { 306 struct snd_sb_csp_mc_header info; 307 308 unsigned char __user *data_ptr; 309 unsigned char __user *data_end; 310 unsigned short func_nr = 0; 311 312 struct riff_header file_h, item_h, code_h; 313 __u32 item_type; 314 struct desc_header funcdesc_h; 315 316 unsigned long flags; 317 int err; 318 319 if (copy_from_user(&info, mcode, sizeof(info))) 320 return -EFAULT; 321 data_ptr = mcode->data; 322 323 if (copy_from_user(&file_h, data_ptr, sizeof(file_h))) 324 return -EFAULT; 325 if ((file_h.name != RIFF_HEADER) || 326 (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) { 327 snd_printd("%s: Invalid RIFF header\n", __FUNCTION__); 328 return -EINVAL; 329 } 330 data_ptr += sizeof(file_h); 331 data_end = data_ptr + le32_to_cpu(file_h.len); 332 333 if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) 334 return -EFAULT; 335 if (item_type != CSP__HEADER) { 336 snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__); 337 return -EINVAL; 338 } 339 data_ptr += sizeof (item_type); 340 341 for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) { 342 if (copy_from_user(&item_h, data_ptr, sizeof(item_h))) 343 return -EFAULT; 344 data_ptr += sizeof(item_h); 345 if (item_h.name != LIST_HEADER) 346 continue; 347 348 if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) 349 return -EFAULT; 350 switch (item_type) { 351 case FUNC_HEADER: 352 if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h))) 353 return -EFAULT; 354 func_nr = le16_to_cpu(funcdesc_h.func_nr); 355 break; 356 case CODE_HEADER: 357 if (func_nr != info.func_req) 358 break; /* not required function, try next */ 359 data_ptr += sizeof(item_type); 360 361 /* destroy QSound mixer element */ 362 if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { 363 snd_sb_qsound_destroy(p); 364 } 365 /* Clear all flags */ 366 p->running = 0; 367 p->mode = 0; 368 369 /* load microcode blocks */ 370 for (;;) { 371 if (data_ptr >= data_end) 372 return -EINVAL; 373 if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) 374 return -EFAULT; 375 376 /* init microcode blocks */ 377 if (code_h.name != INIT_HEADER) 378 break; 379 data_ptr += sizeof(code_h); 380 err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len), 381 SNDRV_SB_CSP_LOAD_INITBLOCK); 382 if (err) 383 return err; 384 data_ptr += le32_to_cpu(code_h.len); 385 } 386 /* main microcode block */ 387 if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) 388 return -EFAULT; 389 390 if (code_h.name != MAIN_HEADER) { 391 snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__); 392 return -EINVAL; 393 } 394 data_ptr += sizeof(code_h); 395 err = snd_sb_csp_load_user(p, data_ptr, 396 le32_to_cpu(code_h.len), 0); 397 if (err) 398 return err; 399 400 /* fill in codec header */ 401 strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name)); 402 p->func_nr = func_nr; 403 p->mode = le16_to_cpu(funcdesc_h.flags_play_rec); 404 switch (le16_to_cpu(funcdesc_h.VOC_type)) { 405 case 0x0001: /* QSound decoder */ 406 if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) { 407 if (snd_sb_qsound_build(p) == 0) 408 /* set QSound flag and clear all other mode flags */ 409 p->mode = SNDRV_SB_CSP_MODE_QSOUND; 410 } 411 p->acc_format = 0; 412 break; 413 case 0x0006: /* A Law codec */ 414 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; 415 break; 416 case 0x0007: /* Mu Law codec */ 417 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; 418 break; 419 case 0x0011: /* what Creative thinks is IMA ADPCM codec */ 420 case 0x0200: /* Creative ADPCM codec */ 421 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; 422 break; 423 case 201: /* Text 2 Speech decoder */ 424 /* TODO: Text2Speech handling routines */ 425 p->acc_format = 0; 426 break; 427 case 0x0202: /* Fast Speech 8 codec */ 428 case 0x0203: /* Fast Speech 10 codec */ 429 p->acc_format = SNDRV_PCM_FMTBIT_SPECIAL; 430 break; 431 default: /* other codecs are unsupported */ 432 p->acc_format = p->acc_width = p->acc_rates = 0; 433 p->mode = 0; 434 snd_printd("%s: Unsupported CSP codec type: 0x%04x\n", 435 __FUNCTION__, 436 le16_to_cpu(funcdesc_h.VOC_type)); 437 return -EINVAL; 438 } 439 p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono); 440 p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit); 441 p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates); 442 443 /* Decouple CSP from IRQ and DMAREQ lines */ 444 spin_lock_irqsave(&p->chip->reg_lock, flags); 445 set_mode_register(p->chip, 0xfc); 446 set_mode_register(p->chip, 0x00); 447 spin_unlock_irqrestore(&p->chip->reg_lock, flags); 448 449 /* finished loading successfully */ 450 p->running = SNDRV_SB_CSP_ST_LOADED; /* set LOADED flag */ 451 return 0; 452 } 453 } 454 snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req); 455 return -EINVAL; 456 } 457 458 /* 459 * unload CSP microcode 460 */ 461 static int snd_sb_csp_unload(struct snd_sb_csp * p) 462 { 463 if (p->running & SNDRV_SB_CSP_ST_RUNNING) 464 return -EBUSY; 465 if (!(p->running & SNDRV_SB_CSP_ST_LOADED)) 466 return -ENXIO; 467 468 /* clear supported formats */ 469 p->acc_format = 0; 470 p->acc_channels = p->acc_width = p->acc_rates = 0; 471 /* destroy QSound mixer element */ 472 if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { 473 snd_sb_qsound_destroy(p); 474 } 475 /* clear all flags */ 476 p->running = 0; 477 p->mode = 0; 478 return 0; 479 } 480 481 /* 482 * send command sequence to DSP 483 */ 484 static inline int command_seq(struct snd_sb *chip, const unsigned char *seq, int size) 485 { 486 int i; 487 for (i = 0; i < size; i++) { 488 if (!snd_sbdsp_command(chip, seq[i])) 489 return -EIO; 490 } 491 return 0; 492 } 493 494 /* 495 * set CSP codec parameter 496 */ 497 static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val) 498 { 499 unsigned char dsp_cmd[3]; 500 501 dsp_cmd[0] = 0x05; /* CSP set codec parameter */ 502 dsp_cmd[1] = val; /* Parameter value */ 503 dsp_cmd[2] = par; /* Parameter */ 504 command_seq(chip, dsp_cmd, 3); 505 snd_sbdsp_command(chip, 0x03); /* DSP read? */ 506 if (snd_sbdsp_get_byte(chip) != par) 507 return -EIO; 508 return 0; 509 } 510 511 /* 512 * set CSP register 513 */ 514 static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val) 515 { 516 unsigned char dsp_cmd[3]; 517 518 dsp_cmd[0] = 0x0e; /* CSP set register */ 519 dsp_cmd[1] = reg; /* CSP Register */ 520 dsp_cmd[2] = val; /* value */ 521 return command_seq(chip, dsp_cmd, 3); 522 } 523 524 /* 525 * read CSP register 526 * return < 0 -> error 527 */ 528 static int read_register(struct snd_sb *chip, unsigned char reg) 529 { 530 unsigned char dsp_cmd[2]; 531 532 dsp_cmd[0] = 0x0f; /* CSP read register */ 533 dsp_cmd[1] = reg; /* CSP Register */ 534 command_seq(chip, dsp_cmd, 2); 535 return snd_sbdsp_get_byte(chip); /* Read DSP value */ 536 } 537 538 /* 539 * set CSP mode register 540 */ 541 static int set_mode_register(struct snd_sb *chip, unsigned char mode) 542 { 543 unsigned char dsp_cmd[2]; 544 545 dsp_cmd[0] = 0x04; /* CSP set mode register */ 546 dsp_cmd[1] = mode; /* mode */ 547 return command_seq(chip, dsp_cmd, 2); 548 } 549 550 /* 551 * Detect CSP 552 * return 0 if CSP exists. 553 */ 554 static int csp_detect(struct snd_sb *chip, int *version) 555 { 556 unsigned char csp_test1, csp_test2; 557 unsigned long flags; 558 int result = -ENODEV; 559 560 spin_lock_irqsave(&chip->reg_lock, flags); 561 562 set_codec_parameter(chip, 0x00, 0x00); 563 set_mode_register(chip, 0xfc); /* 0xfc = ?? */ 564 565 csp_test1 = read_register(chip, 0x83); 566 set_register(chip, 0x83, ~csp_test1); 567 csp_test2 = read_register(chip, 0x83); 568 if (csp_test2 != (csp_test1 ^ 0xff)) 569 goto __fail; 570 571 set_register(chip, 0x83, csp_test1); 572 csp_test2 = read_register(chip, 0x83); 573 if (csp_test2 != csp_test1) 574 goto __fail; 575 576 set_mode_register(chip, 0x00); /* 0x00 = ? */ 577 578 *version = get_version(chip); 579 snd_sbdsp_reset(chip); /* reset DSP after getversion! */ 580 if (*version >= 0x10 && *version <= 0x1f) 581 result = 0; /* valid version id */ 582 583 __fail: 584 spin_unlock_irqrestore(&chip->reg_lock, flags); 585 return result; 586 } 587 588 /* 589 * get CSP version number 590 */ 591 static int get_version(struct snd_sb *chip) 592 { 593 unsigned char dsp_cmd[2]; 594 595 dsp_cmd[0] = 0x08; /* SB_DSP_!something! */ 596 dsp_cmd[1] = 0x03; /* get chip version id? */ 597 command_seq(chip, dsp_cmd, 2); 598 599 return (snd_sbdsp_get_byte(chip)); 600 } 601 602 /* 603 * check if the CSP version is valid 604 */ 605 static int snd_sb_csp_check_version(struct snd_sb_csp * p) 606 { 607 if (p->version < 0x10 || p->version > 0x1f) { 608 snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version); 609 return 1; 610 } 611 return 0; 612 } 613 614 /* 615 * download microcode to CSP (microcode should have one "main" block). 616 */ 617 static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int size, int load_flags) 618 { 619 int status, i; 620 int err; 621 int result = -EIO; 622 unsigned long flags; 623 624 spin_lock_irqsave(&p->chip->reg_lock, flags); 625 snd_sbdsp_command(p->chip, 0x01); /* CSP download command */ 626 if (snd_sbdsp_get_byte(p->chip)) { 627 snd_printd("%s: Download command failed\n", __FUNCTION__); 628 goto __fail; 629 } 630 /* Send CSP low byte (size - 1) */ 631 snd_sbdsp_command(p->chip, (unsigned char)(size - 1)); 632 /* Send high byte */ 633 snd_sbdsp_command(p->chip, (unsigned char)((size - 1) >> 8)); 634 /* send microcode sequence */ 635 /* load from kernel space */ 636 while (size--) { 637 if (!snd_sbdsp_command(p->chip, *buf++)) 638 goto __fail; 639 } 640 if (snd_sbdsp_get_byte(p->chip)) 641 goto __fail; 642 643 if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) { 644 i = 0; 645 /* some codecs (FastSpeech) take some time to initialize */ 646 while (1) { 647 snd_sbdsp_command(p->chip, 0x03); 648 status = snd_sbdsp_get_byte(p->chip); 649 if (status == 0x55 || ++i >= 10) 650 break; 651 udelay (10); 652 } 653 if (status != 0x55) { 654 snd_printd("%s: Microcode initialization failed\n", __FUNCTION__); 655 goto __fail; 656 } 657 } else { 658 /* 659 * Read mixer register SB_DSP4_DMASETUP after loading 'main' code. 660 * Start CSP chip if no 16bit DMA channel is set - some kind 661 * of autorun or perhaps a bugfix? 662 */ 663 spin_lock(&p->chip->mixer_lock); 664 status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP); 665 spin_unlock(&p->chip->mixer_lock); 666 if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) { 667 err = (set_codec_parameter(p->chip, 0xaa, 0x00) || 668 set_codec_parameter(p->chip, 0xff, 0x00)); 669 snd_sbdsp_reset(p->chip); /* really! */ 670 if (err) 671 goto __fail; 672 set_mode_register(p->chip, 0xc0); /* c0 = STOP */ 673 set_mode_register(p->chip, 0x70); /* 70 = RUN */ 674 } 675 } 676 result = 0; 677 678 __fail: 679 spin_unlock_irqrestore(&p->chip->reg_lock, flags); 680 return result; 681 } 682 683 static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags) 684 { 685 int err = -ENOMEM; 686 unsigned char *kbuf = kmalloc(size, GFP_KERNEL); 687 if (kbuf) { 688 if (copy_from_user(kbuf, buf, size)) 689 err = -EFAULT; 690 else 691 err = snd_sb_csp_load(p, kbuf, size, load_flags); 692 kfree(kbuf); 693 } 694 return err; 695 } 696 697 #ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL 698 #include "sb16_csp_codecs.h" 699 700 static const struct firmware snd_sb_csp_static_programs[] = { 701 { .data = mulaw_main, .size = sizeof mulaw_main }, 702 { .data = alaw_main, .size = sizeof alaw_main }, 703 { .data = ima_adpcm_init, .size = sizeof ima_adpcm_init }, 704 { .data = ima_adpcm_playback, .size = sizeof ima_adpcm_playback }, 705 { .data = ima_adpcm_capture, .size = sizeof ima_adpcm_capture }, 706 }; 707 #endif 708 709 static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) 710 { 711 static const char *const names[] = { 712 "sb16/mulaw_main.csp", 713 "sb16/alaw_main.csp", 714 "sb16/ima_adpcm_init.csp", 715 "sb16/ima_adpcm_playback.csp", 716 "sb16/ima_adpcm_capture.csp", 717 }; 718 const struct firmware *program; 719 720 BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT); 721 program = p->csp_programs[index]; 722 if (!program) { 723 #ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL 724 program = &snd_sb_csp_static_programs[index]; 725 #else 726 int err = request_firmware(&program, names[index], 727 p->chip->card->dev); 728 if (err < 0) 729 return err; 730 #endif 731 p->csp_programs[index] = program; 732 } 733 return snd_sb_csp_load(p, program->data, program->size, flags); 734 } 735 736 /* 737 * autoload hardware codec if necessary 738 * return 0 if CSP is loaded and ready to run (p->running != 0) 739 */ 740 static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode) 741 { 742 unsigned long flags; 743 int err = 0; 744 745 /* if CSP is running or manually loaded then exit */ 746 if (p->running & (SNDRV_SB_CSP_ST_RUNNING | SNDRV_SB_CSP_ST_LOADED)) 747 return -EBUSY; 748 749 /* autoload microcode only if requested hardware codec is not already loaded */ 750 if (((1 << pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) { 751 p->running = SNDRV_SB_CSP_ST_AUTO; 752 } else { 753 switch (pcm_sfmt) { 754 case SNDRV_PCM_FORMAT_MU_LAW: 755 err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0); 756 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; 757 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; 758 break; 759 case SNDRV_PCM_FORMAT_A_LAW: 760 err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0); 761 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; 762 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; 763 break; 764 case SNDRV_PCM_FORMAT_IMA_ADPCM: 765 err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT, 766 SNDRV_SB_CSP_LOAD_INITBLOCK); 767 if (err) 768 break; 769 if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) { 770 err = snd_sb_csp_firmware_load 771 (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0); 772 p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE; 773 } else { 774 err = snd_sb_csp_firmware_load 775 (p, CSP_PROGRAM_ADPCM_CAPTURE, 0); 776 p->mode = SNDRV_SB_CSP_MODE_DSP_READ; 777 } 778 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; 779 break; 780 default: 781 /* Decouple CSP from IRQ and DMAREQ lines */ 782 if (p->running & SNDRV_SB_CSP_ST_AUTO) { 783 spin_lock_irqsave(&p->chip->reg_lock, flags); 784 set_mode_register(p->chip, 0xfc); 785 set_mode_register(p->chip, 0x00); 786 spin_unlock_irqrestore(&p->chip->reg_lock, flags); 787 p->running = 0; /* clear autoloaded flag */ 788 } 789 return -EINVAL; 790 } 791 if (err) { 792 p->acc_format = 0; 793 p->acc_channels = p->acc_width = p->acc_rates = 0; 794 795 p->running = 0; /* clear autoloaded flag */ 796 p->mode = 0; 797 return (err); 798 } else { 799 p->running = SNDRV_SB_CSP_ST_AUTO; /* set autoloaded flag */ 800 p->acc_width = SNDRV_SB_CSP_SAMPLE_16BIT; /* only 16 bit data */ 801 p->acc_channels = SNDRV_SB_CSP_MONO | SNDRV_SB_CSP_STEREO; 802 p->acc_rates = SNDRV_SB_CSP_RATE_ALL; /* HW codecs accept all rates */ 803 } 804 805 } 806 return (p->running & SNDRV_SB_CSP_ST_AUTO) ? 0 : -ENXIO; 807 } 808 809 /* 810 * start CSP 811 */ 812 static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels) 813 { 814 unsigned char s_type; /* sample type */ 815 unsigned char mixL, mixR; 816 int result = -EIO; 817 unsigned long flags; 818 819 if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) { 820 snd_printd("%s: Microcode not loaded\n", __FUNCTION__); 821 return -ENXIO; 822 } 823 if (p->running & SNDRV_SB_CSP_ST_RUNNING) { 824 snd_printd("%s: CSP already running\n", __FUNCTION__); 825 return -EBUSY; 826 } 827 if (!(sample_width & p->acc_width)) { 828 snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__); 829 return -EINVAL; 830 } 831 if (!(channels & p->acc_channels)) { 832 snd_printd("%s: Invalid number of channels\n", __FUNCTION__); 833 return -EINVAL; 834 } 835 836 /* Mute PCM volume */ 837 spin_lock_irqsave(&p->chip->mixer_lock, flags); 838 mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); 839 mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); 840 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); 841 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); 842 843 spin_lock(&p->chip->reg_lock); 844 set_mode_register(p->chip, 0xc0); /* c0 = STOP */ 845 set_mode_register(p->chip, 0x70); /* 70 = RUN */ 846 847 s_type = 0x00; 848 if (channels == SNDRV_SB_CSP_MONO) 849 s_type = 0x11; /* 000n 000n (n = 1 if mono) */ 850 if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT) 851 s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */ 852 853 if (set_codec_parameter(p->chip, 0x81, s_type)) { 854 snd_printd("%s: Set sample type command failed\n", __FUNCTION__); 855 goto __fail; 856 } 857 if (set_codec_parameter(p->chip, 0x80, 0x00)) { 858 snd_printd("%s: Codec start command failed\n", __FUNCTION__); 859 goto __fail; 860 } 861 p->run_width = sample_width; 862 p->run_channels = channels; 863 864 p->running |= SNDRV_SB_CSP_ST_RUNNING; 865 866 if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) { 867 set_codec_parameter(p->chip, 0xe0, 0x01); 868 /* enable QSound decoder */ 869 set_codec_parameter(p->chip, 0x00, 0xff); 870 set_codec_parameter(p->chip, 0x01, 0xff); 871 p->running |= SNDRV_SB_CSP_ST_QSOUND; 872 /* set QSound startup value */ 873 snd_sb_csp_qsound_transfer(p); 874 } 875 result = 0; 876 877 __fail: 878 spin_unlock(&p->chip->reg_lock); 879 880 /* restore PCM volume */ 881 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); 882 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); 883 spin_unlock_irqrestore(&p->chip->mixer_lock, flags); 884 885 return result; 886 } 887 888 /* 889 * stop CSP 890 */ 891 static int snd_sb_csp_stop(struct snd_sb_csp * p) 892 { 893 int result; 894 unsigned char mixL, mixR; 895 unsigned long flags; 896 897 if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) 898 return 0; 899 900 /* Mute PCM volume */ 901 spin_lock_irqsave(&p->chip->mixer_lock, flags); 902 mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); 903 mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); 904 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); 905 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); 906 907 spin_lock(&p->chip->reg_lock); 908 if (p->running & SNDRV_SB_CSP_ST_QSOUND) { 909 set_codec_parameter(p->chip, 0xe0, 0x01); 910 /* disable QSound decoder */ 911 set_codec_parameter(p->chip, 0x00, 0x00); 912 set_codec_parameter(p->chip, 0x01, 0x00); 913 914 p->running &= ~SNDRV_SB_CSP_ST_QSOUND; 915 } 916 result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */ 917 spin_unlock(&p->chip->reg_lock); 918 919 /* restore PCM volume */ 920 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); 921 snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); 922 spin_unlock_irqrestore(&p->chip->mixer_lock, flags); 923 924 if (!(result)) 925 p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING); 926 return result; 927 } 928 929 /* 930 * pause CSP codec and hold DMA transfer 931 */ 932 static int snd_sb_csp_pause(struct snd_sb_csp * p) 933 { 934 int result; 935 unsigned long flags; 936 937 if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) 938 return -EBUSY; 939 940 spin_lock_irqsave(&p->chip->reg_lock, flags); 941 result = set_codec_parameter(p->chip, 0x80, 0xff); 942 spin_unlock_irqrestore(&p->chip->reg_lock, flags); 943 if (!(result)) 944 p->running |= SNDRV_SB_CSP_ST_PAUSED; 945 946 return result; 947 } 948 949 /* 950 * restart CSP codec and resume DMA transfer 951 */ 952 static int snd_sb_csp_restart(struct snd_sb_csp * p) 953 { 954 int result; 955 unsigned long flags; 956 957 if (!(p->running & SNDRV_SB_CSP_ST_PAUSED)) 958 return -EBUSY; 959 960 spin_lock_irqsave(&p->chip->reg_lock, flags); 961 result = set_codec_parameter(p->chip, 0x80, 0x00); 962 spin_unlock_irqrestore(&p->chip->reg_lock, flags); 963 if (!(result)) 964 p->running &= ~SNDRV_SB_CSP_ST_PAUSED; 965 966 return result; 967 } 968 969 /* ------------------------------ */ 970 971 /* 972 * QSound mixer control for PCM 973 */ 974 975 static int snd_sb_qsound_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 976 { 977 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 978 uinfo->count = 1; 979 uinfo->value.integer.min = 0; 980 uinfo->value.integer.max = 1; 981 return 0; 982 } 983 984 static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 985 { 986 struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); 987 988 ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0; 989 return 0; 990 } 991 992 static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 993 { 994 struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); 995 unsigned long flags; 996 int change; 997 unsigned char nval; 998 999 nval = ucontrol->value.integer.value[0] & 0x01; 1000 spin_lock_irqsave(&p->q_lock, flags); 1001 change = p->q_enabled != nval; 1002 p->q_enabled = nval; 1003 spin_unlock_irqrestore(&p->q_lock, flags); 1004 return change; 1005 } 1006 1007 static int snd_sb_qsound_space_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1008 { 1009 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1010 uinfo->count = 2; 1011 uinfo->value.integer.min = 0; 1012 uinfo->value.integer.max = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; 1013 return 0; 1014 } 1015 1016 static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1017 { 1018 struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); 1019 unsigned long flags; 1020 1021 spin_lock_irqsave(&p->q_lock, flags); 1022 ucontrol->value.integer.value[0] = p->qpos_left; 1023 ucontrol->value.integer.value[1] = p->qpos_right; 1024 spin_unlock_irqrestore(&p->q_lock, flags); 1025 return 0; 1026 } 1027 1028 static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 1029 { 1030 struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); 1031 unsigned long flags; 1032 int change; 1033 unsigned char nval1, nval2; 1034 1035 nval1 = ucontrol->value.integer.value[0]; 1036 if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) 1037 nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; 1038 nval2 = ucontrol->value.integer.value[1]; 1039 if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) 1040 nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; 1041 spin_lock_irqsave(&p->q_lock, flags); 1042 change = p->qpos_left != nval1 || p->qpos_right != nval2; 1043 p->qpos_left = nval1; 1044 p->qpos_right = nval2; 1045 p->qpos_changed = change; 1046 spin_unlock_irqrestore(&p->q_lock, flags); 1047 return change; 1048 } 1049 1050 static struct snd_kcontrol_new snd_sb_qsound_switch = { 1051 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1052 .name = "3D Control - Switch", 1053 .info = snd_sb_qsound_switch_info, 1054 .get = snd_sb_qsound_switch_get, 1055 .put = snd_sb_qsound_switch_put 1056 }; 1057 1058 static struct snd_kcontrol_new snd_sb_qsound_space = { 1059 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1060 .name = "3D Control - Space", 1061 .info = snd_sb_qsound_space_info, 1062 .get = snd_sb_qsound_space_get, 1063 .put = snd_sb_qsound_space_put 1064 }; 1065 1066 static int snd_sb_qsound_build(struct snd_sb_csp * p) 1067 { 1068 struct snd_card *card; 1069 int err; 1070 1071 snd_assert(p != NULL, return -EINVAL); 1072 1073 card = p->chip->card; 1074 p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2; 1075 p->qpos_changed = 0; 1076 1077 spin_lock_init(&p->q_lock); 1078 1079 if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) 1080 goto __error; 1081 if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) 1082 goto __error; 1083 1084 return 0; 1085 1086 __error: 1087 snd_sb_qsound_destroy(p); 1088 return err; 1089 } 1090 1091 static void snd_sb_qsound_destroy(struct snd_sb_csp * p) 1092 { 1093 struct snd_card *card; 1094 unsigned long flags; 1095 1096 snd_assert(p != NULL, return); 1097 1098 card = p->chip->card; 1099 1100 down_write(&card->controls_rwsem); 1101 if (p->qsound_switch) 1102 snd_ctl_remove(card, p->qsound_switch); 1103 if (p->qsound_space) 1104 snd_ctl_remove(card, p->qsound_space); 1105 up_write(&card->controls_rwsem); 1106 1107 /* cancel pending transfer of QSound parameters */ 1108 spin_lock_irqsave (&p->q_lock, flags); 1109 p->qpos_changed = 0; 1110 spin_unlock_irqrestore (&p->q_lock, flags); 1111 } 1112 1113 /* 1114 * Transfer qsound parameters to CSP, 1115 * function should be called from interrupt routine 1116 */ 1117 static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p) 1118 { 1119 int err = -ENXIO; 1120 1121 spin_lock(&p->q_lock); 1122 if (p->running & SNDRV_SB_CSP_ST_QSOUND) { 1123 set_codec_parameter(p->chip, 0xe0, 0x01); 1124 /* left channel */ 1125 set_codec_parameter(p->chip, 0x00, p->qpos_left); 1126 set_codec_parameter(p->chip, 0x02, 0x00); 1127 /* right channel */ 1128 set_codec_parameter(p->chip, 0x00, p->qpos_right); 1129 set_codec_parameter(p->chip, 0x03, 0x00); 1130 err = 0; 1131 } 1132 p->qpos_changed = 0; 1133 spin_unlock(&p->q_lock); 1134 return err; 1135 } 1136 1137 /* ------------------------------ */ 1138 1139 /* 1140 * proc interface 1141 */ 1142 static int init_proc_entry(struct snd_sb_csp * p, int device) 1143 { 1144 char name[16]; 1145 struct snd_info_entry *entry; 1146 sprintf(name, "cspD%d", device); 1147 if (! snd_card_proc_new(p->chip->card, name, &entry)) 1148 snd_info_set_text_ops(entry, p, info_read); 1149 return 0; 1150 } 1151 1152 static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 1153 { 1154 struct snd_sb_csp *p = entry->private_data; 1155 1156 snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f)); 1157 snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'), 1158 ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'), 1159 ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'), 1160 ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-')); 1161 if (p->running & SNDRV_SB_CSP_ST_LOADED) { 1162 snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr); 1163 snd_iprintf(buffer, "Sample rates: "); 1164 if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) { 1165 snd_iprintf(buffer, "All\n"); 1166 } else { 1167 snd_iprintf(buffer, "%s%s%s%s\n", 1168 ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""), 1169 ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""), 1170 ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""), 1171 ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : "")); 1172 } 1173 if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { 1174 snd_iprintf(buffer, "QSound decoder %sabled\n", 1175 p->q_enabled ? "en" : "dis"); 1176 } else { 1177 snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n", 1178 p->acc_format, 1179 ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"), 1180 ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"), 1181 ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"), 1182 ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"), 1183 ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"), 1184 ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-")); 1185 } 1186 } 1187 if (p->running & SNDRV_SB_CSP_ST_AUTO) { 1188 snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n"); 1189 } 1190 if (p->running & SNDRV_SB_CSP_ST_RUNNING) { 1191 snd_iprintf(buffer, "Processing %dbit %s PCM samples\n", 1192 ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8), 1193 ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo")); 1194 } 1195 if (p->running & SNDRV_SB_CSP_ST_QSOUND) { 1196 snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n", 1197 p->qpos_left, p->qpos_right); 1198 } 1199 } 1200 1201 /* */ 1202 1203 EXPORT_SYMBOL(snd_sb_csp_new); 1204 1205 /* 1206 * INIT part 1207 */ 1208 1209 static int __init alsa_sb_csp_init(void) 1210 { 1211 return 0; 1212 } 1213 1214 static void __exit alsa_sb_csp_exit(void) 1215 { 1216 } 1217 1218 module_init(alsa_sb_csp_init) 1219 module_exit(alsa_sb_csp_exit) 1220