root/sound/isa/sb/sb16_csp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_sb_csp_new
  2. snd_sb_csp_free
  3. snd_sb_csp_open
  4. snd_sb_csp_ioctl
  5. snd_sb_csp_release
  6. snd_sb_csp_use
  7. snd_sb_csp_unuse
  8. snd_sb_csp_riff_load
  9. snd_sb_csp_unload
  10. command_seq
  11. set_codec_parameter
  12. set_register
  13. read_register
  14. set_mode_register
  15. csp_detect
  16. get_version
  17. snd_sb_csp_check_version
  18. snd_sb_csp_load
  19. snd_sb_csp_load_user
  20. snd_sb_csp_firmware_load
  21. snd_sb_csp_autoload
  22. snd_sb_csp_start
  23. snd_sb_csp_stop
  24. snd_sb_csp_pause
  25. snd_sb_csp_restart
  26. snd_sb_qsound_switch_get
  27. snd_sb_qsound_switch_put
  28. snd_sb_qsound_space_info
  29. snd_sb_qsound_space_get
  30. snd_sb_qsound_space_put
  31. snd_sb_qsound_build
  32. snd_sb_qsound_destroy
  33. snd_sb_csp_qsound_transfer
  34. init_proc_entry
  35. info_read

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

/* [<][>][^][v][top][bottom][index][help] */