Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
0004  *                        Takashi Iwai <tiwai@suse.de>
0005  *
0006  *  SB16ASP/AWE32 CSP control
0007  *
0008  *  CSP microcode loader:
0009  *   alsa-tools/sb16_csp/ 
0010  */
0011 
0012 #include <linux/delay.h>
0013 #include <linux/init.h>
0014 #include <linux/slab.h>
0015 #include <linux/module.h>
0016 #include <sound/core.h>
0017 #include <sound/control.h>
0018 #include <sound/info.h>
0019 #include <sound/sb16_csp.h>
0020 #include <sound/initval.h>
0021 
0022 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
0023 MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
0024 MODULE_LICENSE("GPL");
0025 MODULE_FIRMWARE("sb16/mulaw_main.csp");
0026 MODULE_FIRMWARE("sb16/alaw_main.csp");
0027 MODULE_FIRMWARE("sb16/ima_adpcm_init.csp");
0028 MODULE_FIRMWARE("sb16/ima_adpcm_playback.csp");
0029 MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp");
0030 
0031 #ifdef SNDRV_LITTLE_ENDIAN
0032 #define CSP_HDR_VALUE(a,b,c,d)  ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
0033 #else
0034 #define CSP_HDR_VALUE(a,b,c,d)  ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
0035 #endif
0036 
0037 #define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F')
0038 #define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ')
0039 #define LIST_HEADER CSP_HDR_VALUE('L', 'I', 'S', 'T')
0040 #define FUNC_HEADER CSP_HDR_VALUE('f', 'u', 'n', 'c')
0041 #define CODE_HEADER CSP_HDR_VALUE('c', 'o', 'd', 'e')
0042 #define INIT_HEADER CSP_HDR_VALUE('i', 'n', 'i', 't')
0043 #define MAIN_HEADER CSP_HDR_VALUE('m', 'a', 'i', 'n')
0044 
0045 /*
0046  * RIFF data format
0047  */
0048 struct riff_header {
0049     __le32 name;
0050     __le32 len;
0051 };
0052 
0053 struct desc_header {
0054     struct riff_header info;
0055     __le16 func_nr;
0056     __le16 VOC_type;
0057     __le16 flags_play_rec;
0058     __le16 flags_16bit_8bit;
0059     __le16 flags_stereo_mono;
0060     __le16 flags_rates;
0061 };
0062 
0063 /*
0064  * prototypes
0065  */
0066 static void snd_sb_csp_free(struct snd_hwdep *hw);
0067 static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file);
0068 static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg);
0069 static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file);
0070 
0071 static int csp_detect(struct snd_sb *chip, int *version);
0072 static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val);
0073 static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val);
0074 static int read_register(struct snd_sb *chip, unsigned char reg);
0075 static int set_mode_register(struct snd_sb *chip, unsigned char mode);
0076 static int get_version(struct snd_sb *chip);
0077 
0078 static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
0079                 struct snd_sb_csp_microcode __user * code);
0080 static int snd_sb_csp_unload(struct snd_sb_csp * p);
0081 static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags);
0082 static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, int play_rec_mode);
0083 static int snd_sb_csp_check_version(struct snd_sb_csp * p);
0084 
0085 static int snd_sb_csp_use(struct snd_sb_csp * p);
0086 static int snd_sb_csp_unuse(struct snd_sb_csp * p);
0087 static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels);
0088 static int snd_sb_csp_stop(struct snd_sb_csp * p);
0089 static int snd_sb_csp_pause(struct snd_sb_csp * p);
0090 static int snd_sb_csp_restart(struct snd_sb_csp * p);
0091 
0092 static int snd_sb_qsound_build(struct snd_sb_csp * p);
0093 static void snd_sb_qsound_destroy(struct snd_sb_csp * p);
0094 static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p);
0095 
0096 static int init_proc_entry(struct snd_sb_csp * p, int device);
0097 static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
0098 
0099 /*
0100  * Detect CSP chip and create a new instance
0101  */
0102 int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep)
0103 {
0104     struct snd_sb_csp *p;
0105     int version;
0106     int err;
0107     struct snd_hwdep *hw;
0108 
0109     if (rhwdep)
0110         *rhwdep = NULL;
0111 
0112     if (csp_detect(chip, &version))
0113         return -ENODEV;
0114 
0115     err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw);
0116     if (err < 0)
0117         return err;
0118 
0119     p = kzalloc(sizeof(*p), GFP_KERNEL);
0120     if (!p) {
0121         snd_device_free(chip->card, hw);
0122         return -ENOMEM;
0123     }
0124     p->chip = chip;
0125     p->version = version;
0126 
0127     /* CSP operators */
0128     p->ops.csp_use = snd_sb_csp_use;
0129     p->ops.csp_unuse = snd_sb_csp_unuse;
0130     p->ops.csp_autoload = snd_sb_csp_autoload;
0131     p->ops.csp_start = snd_sb_csp_start;
0132     p->ops.csp_stop = snd_sb_csp_stop;
0133     p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer;
0134 
0135     mutex_init(&p->access_mutex);
0136     sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f));
0137     hw->iface = SNDRV_HWDEP_IFACE_SB16CSP;
0138     hw->private_data = p;
0139     hw->private_free = snd_sb_csp_free;
0140 
0141     /* operators - only write/ioctl */
0142     hw->ops.open = snd_sb_csp_open;
0143     hw->ops.ioctl = snd_sb_csp_ioctl;
0144     hw->ops.release = snd_sb_csp_release;
0145 
0146     /* create a proc entry */
0147     init_proc_entry(p, device);
0148     if (rhwdep)
0149         *rhwdep = hw;
0150     return 0;
0151 }
0152 
0153 /*
0154  * free_private for hwdep instance
0155  */
0156 static void snd_sb_csp_free(struct snd_hwdep *hwdep)
0157 {
0158     int i;
0159     struct snd_sb_csp *p = hwdep->private_data;
0160     if (p) {
0161         if (p->running & SNDRV_SB_CSP_ST_RUNNING)
0162             snd_sb_csp_stop(p);
0163         for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i)
0164             release_firmware(p->csp_programs[i]);
0165         kfree(p);
0166     }
0167 }
0168 
0169 /* ------------------------------ */
0170 
0171 /*
0172  * open the device exclusively
0173  */
0174 static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file)
0175 {
0176     struct snd_sb_csp *p = hw->private_data;
0177     return (snd_sb_csp_use(p));
0178 }
0179 
0180 /*
0181  * ioctl for hwdep device:
0182  */
0183 static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg)
0184 {
0185     struct snd_sb_csp *p = hw->private_data;
0186     struct snd_sb_csp_info info;
0187     struct snd_sb_csp_start start_info;
0188     int err;
0189 
0190     if (snd_BUG_ON(!p))
0191         return -EINVAL;
0192 
0193     if (snd_sb_csp_check_version(p))
0194         return -ENODEV;
0195 
0196     switch (cmd) {
0197         /* get information */
0198     case SNDRV_SB_CSP_IOCTL_INFO:
0199         memset(&info, 0, sizeof(info));
0200         *info.codec_name = *p->codec_name;
0201         info.func_nr = p->func_nr;
0202         info.acc_format = p->acc_format;
0203         info.acc_channels = p->acc_channels;
0204         info.acc_width = p->acc_width;
0205         info.acc_rates = p->acc_rates;
0206         info.csp_mode = p->mode;
0207         info.run_channels = p->run_channels;
0208         info.run_width = p->run_width;
0209         info.version = p->version;
0210         info.state = p->running;
0211         if (copy_to_user((void __user *)arg, &info, sizeof(info)))
0212             err = -EFAULT;
0213         else
0214             err = 0;
0215         break;
0216 
0217         /* load CSP microcode */
0218     case SNDRV_SB_CSP_IOCTL_LOAD_CODE:
0219         err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
0220                -EBUSY : snd_sb_csp_riff_load(p, (struct snd_sb_csp_microcode __user *) arg));
0221         break;
0222     case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE:
0223         err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
0224                -EBUSY : snd_sb_csp_unload(p));
0225         break;
0226 
0227         /* change CSP running state */
0228     case SNDRV_SB_CSP_IOCTL_START:
0229         if (copy_from_user(&start_info, (void __user *) arg, sizeof(start_info)))
0230             err = -EFAULT;
0231         else
0232             err = snd_sb_csp_start(p, start_info.sample_width, start_info.channels);
0233         break;
0234     case SNDRV_SB_CSP_IOCTL_STOP:
0235         err = snd_sb_csp_stop(p);
0236         break;
0237     case SNDRV_SB_CSP_IOCTL_PAUSE:
0238         err = snd_sb_csp_pause(p);
0239         break;
0240     case SNDRV_SB_CSP_IOCTL_RESTART:
0241         err = snd_sb_csp_restart(p);
0242         break;
0243     default:
0244         err = -ENOTTY;
0245         break;
0246     }
0247 
0248     return err;
0249 }
0250 
0251 /*
0252  * close the device
0253  */
0254 static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file)
0255 {
0256     struct snd_sb_csp *p = hw->private_data;
0257     return (snd_sb_csp_unuse(p));
0258 }
0259 
0260 /* ------------------------------ */
0261 
0262 /*
0263  * acquire device
0264  */
0265 static int snd_sb_csp_use(struct snd_sb_csp * p)
0266 {
0267     mutex_lock(&p->access_mutex);
0268     if (p->used) {
0269         mutex_unlock(&p->access_mutex);
0270         return -EAGAIN;
0271     }
0272     p->used++;
0273     mutex_unlock(&p->access_mutex);
0274 
0275     return 0;
0276 
0277 }
0278 
0279 /*
0280  * release device
0281  */
0282 static int snd_sb_csp_unuse(struct snd_sb_csp * p)
0283 {
0284     mutex_lock(&p->access_mutex);
0285     p->used--;
0286     mutex_unlock(&p->access_mutex);
0287 
0288     return 0;
0289 }
0290 
0291 /*
0292  * load microcode via ioctl: 
0293  * code is user-space pointer
0294  */
0295 static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
0296                 struct snd_sb_csp_microcode __user * mcode)
0297 {
0298     struct snd_sb_csp_mc_header info;
0299 
0300     unsigned char __user *data_ptr;
0301     unsigned char __user *data_end;
0302     unsigned short func_nr = 0;
0303 
0304     struct riff_header file_h, item_h, code_h;
0305     __le32 item_type;
0306     struct desc_header funcdesc_h;
0307 
0308     unsigned long flags;
0309     int err;
0310 
0311     if (copy_from_user(&info, mcode, sizeof(info)))
0312         return -EFAULT;
0313     data_ptr = mcode->data;
0314 
0315     if (copy_from_user(&file_h, data_ptr, sizeof(file_h)))
0316         return -EFAULT;
0317     if ((le32_to_cpu(file_h.name) != RIFF_HEADER) ||
0318         (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
0319         snd_printd("%s: Invalid RIFF header\n", __func__);
0320         return -EINVAL;
0321     }
0322     data_ptr += sizeof(file_h);
0323     data_end = data_ptr + le32_to_cpu(file_h.len);
0324 
0325     if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
0326         return -EFAULT;
0327     if (le32_to_cpu(item_type) != CSP__HEADER) {
0328         snd_printd("%s: Invalid RIFF file type\n", __func__);
0329         return -EINVAL;
0330     }
0331     data_ptr += sizeof (item_type);
0332 
0333     for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) {
0334         if (copy_from_user(&item_h, data_ptr, sizeof(item_h)))
0335             return -EFAULT;
0336         data_ptr += sizeof(item_h);
0337         if (le32_to_cpu(item_h.name) != LIST_HEADER)
0338             continue;
0339 
0340         if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
0341              return -EFAULT;
0342         switch (le32_to_cpu(item_type)) {
0343         case FUNC_HEADER:
0344             if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h)))
0345                 return -EFAULT;
0346             func_nr = le16_to_cpu(funcdesc_h.func_nr);
0347             break;
0348         case CODE_HEADER:
0349             if (func_nr != info.func_req)
0350                 break;  /* not required function, try next */
0351             data_ptr += sizeof(item_type);
0352 
0353             /* destroy QSound mixer element */
0354             if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
0355                 snd_sb_qsound_destroy(p);
0356             }
0357             /* Clear all flags */
0358             p->running = 0;
0359             p->mode = 0;
0360 
0361             /* load microcode blocks */
0362             for (;;) {
0363                 if (data_ptr >= data_end)
0364                     return -EINVAL;
0365                 if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
0366                     return -EFAULT;
0367 
0368                 /* init microcode blocks */
0369                 if (le32_to_cpu(code_h.name) != INIT_HEADER)
0370                     break;
0371                 data_ptr += sizeof(code_h);
0372                 err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len),
0373                               SNDRV_SB_CSP_LOAD_INITBLOCK);
0374                 if (err)
0375                     return err;
0376                 data_ptr += le32_to_cpu(code_h.len);
0377             }
0378             /* main microcode block */
0379             if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
0380                 return -EFAULT;
0381 
0382             if (le32_to_cpu(code_h.name) != MAIN_HEADER) {
0383                 snd_printd("%s: Missing 'main' microcode\n", __func__);
0384                 return -EINVAL;
0385             }
0386             data_ptr += sizeof(code_h);
0387             err = snd_sb_csp_load_user(p, data_ptr,
0388                            le32_to_cpu(code_h.len), 0);
0389             if (err)
0390                 return err;
0391 
0392             /* fill in codec header */
0393             strscpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
0394             p->func_nr = func_nr;
0395             p->mode = le16_to_cpu(funcdesc_h.flags_play_rec);
0396             switch (le16_to_cpu(funcdesc_h.VOC_type)) {
0397             case 0x0001:    /* QSound decoder */
0398                 if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
0399                     if (snd_sb_qsound_build(p) == 0)
0400                         /* set QSound flag and clear all other mode flags */
0401                         p->mode = SNDRV_SB_CSP_MODE_QSOUND;
0402                 }
0403                 p->acc_format = 0;
0404                 break;
0405             case 0x0006:    /* A Law codec */
0406                 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
0407                 break;
0408             case 0x0007:    /* Mu Law codec */
0409                 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
0410                 break;
0411             case 0x0011:    /* what Creative thinks is IMA ADPCM codec */
0412             case 0x0200:    /* Creative ADPCM codec */
0413                 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
0414                 break;
0415             case    201:    /* Text 2 Speech decoder */
0416                 /* TODO: Text2Speech handling routines */
0417                 p->acc_format = 0;
0418                 break;
0419             case 0x0202:    /* Fast Speech 8 codec */
0420             case 0x0203:    /* Fast Speech 10 codec */
0421                 p->acc_format = SNDRV_PCM_FMTBIT_SPECIAL;
0422                 break;
0423             default:    /* other codecs are unsupported */
0424                 p->acc_format = p->acc_width = p->acc_rates = 0;
0425                 p->mode = 0;
0426                 snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
0427                        __func__,
0428                        le16_to_cpu(funcdesc_h.VOC_type));
0429                 return -EINVAL;
0430             }
0431             p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono);
0432             p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit);
0433             p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates);
0434 
0435             /* Decouple CSP from IRQ and DMAREQ lines */
0436             spin_lock_irqsave(&p->chip->reg_lock, flags);
0437             set_mode_register(p->chip, 0xfc);
0438             set_mode_register(p->chip, 0x00);
0439             spin_unlock_irqrestore(&p->chip->reg_lock, flags);
0440 
0441             /* finished loading successfully */
0442             p->running = SNDRV_SB_CSP_ST_LOADED;    /* set LOADED flag */
0443             return 0;
0444         }
0445     }
0446     snd_printd("%s: Function #%d not found\n", __func__, info.func_req);
0447     return -EINVAL;
0448 }
0449 
0450 /*
0451  * unload CSP microcode
0452  */
0453 static int snd_sb_csp_unload(struct snd_sb_csp * p)
0454 {
0455     if (p->running & SNDRV_SB_CSP_ST_RUNNING)
0456         return -EBUSY;
0457     if (!(p->running & SNDRV_SB_CSP_ST_LOADED))
0458         return -ENXIO;
0459 
0460     /* clear supported formats */
0461     p->acc_format = 0;
0462     p->acc_channels = p->acc_width = p->acc_rates = 0;
0463     /* destroy QSound mixer element */
0464     if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
0465         snd_sb_qsound_destroy(p);
0466     }
0467     /* clear all flags */
0468     p->running = 0;
0469     p->mode = 0;
0470     return 0;
0471 }
0472 
0473 /*
0474  * send command sequence to DSP
0475  */
0476 static inline int command_seq(struct snd_sb *chip, const unsigned char *seq, int size)
0477 {
0478     int i;
0479     for (i = 0; i < size; i++) {
0480         if (!snd_sbdsp_command(chip, seq[i]))
0481             return -EIO;
0482     }
0483     return 0;
0484 }
0485 
0486 /*
0487  * set CSP codec parameter
0488  */
0489 static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val)
0490 {
0491     unsigned char dsp_cmd[3];
0492 
0493     dsp_cmd[0] = 0x05;  /* CSP set codec parameter */
0494     dsp_cmd[1] = val;   /* Parameter value */
0495     dsp_cmd[2] = par;   /* Parameter */
0496     command_seq(chip, dsp_cmd, 3);
0497     snd_sbdsp_command(chip, 0x03);  /* DSP read? */
0498     if (snd_sbdsp_get_byte(chip) != par)
0499         return -EIO;
0500     return 0;
0501 }
0502 
0503 /*
0504  * set CSP register
0505  */
0506 static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val)
0507 {
0508     unsigned char dsp_cmd[3];
0509 
0510     dsp_cmd[0] = 0x0e;  /* CSP set register */
0511     dsp_cmd[1] = reg;   /* CSP Register */
0512     dsp_cmd[2] = val;   /* value */
0513     return command_seq(chip, dsp_cmd, 3);
0514 }
0515 
0516 /*
0517  * read CSP register
0518  * return < 0 -> error
0519  */
0520 static int read_register(struct snd_sb *chip, unsigned char reg)
0521 {
0522     unsigned char dsp_cmd[2];
0523 
0524     dsp_cmd[0] = 0x0f;  /* CSP read register */
0525     dsp_cmd[1] = reg;   /* CSP Register */
0526     command_seq(chip, dsp_cmd, 2);
0527     return snd_sbdsp_get_byte(chip);    /* Read DSP value */
0528 }
0529 
0530 /*
0531  * set CSP mode register
0532  */
0533 static int set_mode_register(struct snd_sb *chip, unsigned char mode)
0534 {
0535     unsigned char dsp_cmd[2];
0536 
0537     dsp_cmd[0] = 0x04;  /* CSP set mode register */
0538     dsp_cmd[1] = mode;  /* mode */
0539     return command_seq(chip, dsp_cmd, 2);
0540 }
0541 
0542 /*
0543  * Detect CSP
0544  * return 0 if CSP exists.
0545  */
0546 static int csp_detect(struct snd_sb *chip, int *version)
0547 {
0548     unsigned char csp_test1, csp_test2;
0549     unsigned long flags;
0550     int result = -ENODEV;
0551 
0552     spin_lock_irqsave(&chip->reg_lock, flags);
0553 
0554     set_codec_parameter(chip, 0x00, 0x00);
0555     set_mode_register(chip, 0xfc);      /* 0xfc = ?? */
0556 
0557     csp_test1 = read_register(chip, 0x83);
0558     set_register(chip, 0x83, ~csp_test1);
0559     csp_test2 = read_register(chip, 0x83);
0560     if (csp_test2 != (csp_test1 ^ 0xff))
0561         goto __fail;
0562 
0563     set_register(chip, 0x83, csp_test1);
0564     csp_test2 = read_register(chip, 0x83);
0565     if (csp_test2 != csp_test1)
0566         goto __fail;
0567 
0568     set_mode_register(chip, 0x00);      /* 0x00 = ? */
0569 
0570     *version = get_version(chip);
0571     snd_sbdsp_reset(chip);  /* reset DSP after getversion! */
0572     if (*version >= 0x10 && *version <= 0x1f)
0573         result = 0;     /* valid version id */
0574 
0575       __fail:
0576     spin_unlock_irqrestore(&chip->reg_lock, flags);
0577     return result;
0578 }
0579 
0580 /*
0581  * get CSP version number
0582  */
0583 static int get_version(struct snd_sb *chip)
0584 {
0585     unsigned char dsp_cmd[2];
0586 
0587     dsp_cmd[0] = 0x08;  /* SB_DSP_!something! */
0588     dsp_cmd[1] = 0x03;  /* get chip version id? */
0589     command_seq(chip, dsp_cmd, 2);
0590 
0591     return (snd_sbdsp_get_byte(chip));
0592 }
0593 
0594 /*
0595  * check if the CSP version is valid
0596  */
0597 static int snd_sb_csp_check_version(struct snd_sb_csp * p)
0598 {
0599     if (p->version < 0x10 || p->version > 0x1f) {
0600         snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version);
0601         return 1;
0602     }
0603     return 0;
0604 }
0605 
0606 /*
0607  * download microcode to CSP (microcode should have one "main" block).
0608  */
0609 static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int size, int load_flags)
0610 {
0611     int status, i;
0612     int err;
0613     int result = -EIO;
0614     unsigned long flags;
0615 
0616     spin_lock_irqsave(&p->chip->reg_lock, flags);
0617     snd_sbdsp_command(p->chip, 0x01);   /* CSP download command */
0618     if (snd_sbdsp_get_byte(p->chip)) {
0619         snd_printd("%s: Download command failed\n", __func__);
0620         goto __fail;
0621     }
0622     /* Send CSP low byte (size - 1) */
0623     snd_sbdsp_command(p->chip, (unsigned char)(size - 1));
0624     /* Send high byte */
0625     snd_sbdsp_command(p->chip, (unsigned char)((size - 1) >> 8));
0626     /* send microcode sequence */
0627     /* load from kernel space */
0628     while (size--) {
0629         if (!snd_sbdsp_command(p->chip, *buf++))
0630             goto __fail;
0631     }
0632     if (snd_sbdsp_get_byte(p->chip))
0633         goto __fail;
0634 
0635     if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) {
0636         i = 0;
0637         /* some codecs (FastSpeech) take some time to initialize */
0638         while (1) {
0639             snd_sbdsp_command(p->chip, 0x03);
0640             status = snd_sbdsp_get_byte(p->chip);
0641             if (status == 0x55 || ++i >= 10)
0642                 break;
0643             udelay (10);
0644         }
0645         if (status != 0x55) {
0646             snd_printd("%s: Microcode initialization failed\n", __func__);
0647             goto __fail;
0648         }
0649     } else {
0650         /*
0651          * Read mixer register SB_DSP4_DMASETUP after loading 'main' code.
0652          * Start CSP chip if no 16bit DMA channel is set - some kind
0653          * of autorun or perhaps a bugfix?
0654          */
0655         spin_lock(&p->chip->mixer_lock);
0656         status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP);
0657         spin_unlock(&p->chip->mixer_lock);
0658         if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) {
0659             err = (set_codec_parameter(p->chip, 0xaa, 0x00) ||
0660                    set_codec_parameter(p->chip, 0xff, 0x00));
0661             snd_sbdsp_reset(p->chip);       /* really! */
0662             if (err)
0663                 goto __fail;
0664             set_mode_register(p->chip, 0xc0);   /* c0 = STOP */
0665             set_mode_register(p->chip, 0x70);   /* 70 = RUN */
0666         }
0667     }
0668     result = 0;
0669 
0670       __fail:
0671     spin_unlock_irqrestore(&p->chip->reg_lock, flags);
0672     return result;
0673 }
0674  
0675 static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags)
0676 {
0677     int err;
0678     unsigned char *kbuf;
0679 
0680     kbuf = memdup_user(buf, size);
0681     if (IS_ERR(kbuf))
0682         return PTR_ERR(kbuf);
0683 
0684     err = snd_sb_csp_load(p, kbuf, size, load_flags);
0685 
0686     kfree(kbuf);
0687     return err;
0688 }
0689 
0690 static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags)
0691 {
0692     static const char *const names[] = {
0693         "sb16/mulaw_main.csp",
0694         "sb16/alaw_main.csp",
0695         "sb16/ima_adpcm_init.csp",
0696         "sb16/ima_adpcm_playback.csp",
0697         "sb16/ima_adpcm_capture.csp",
0698     };
0699     const struct firmware *program;
0700 
0701     BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT);
0702     program = p->csp_programs[index];
0703     if (!program) {
0704         int err = request_firmware(&program, names[index],
0705                        p->chip->card->dev);
0706         if (err < 0)
0707             return err;
0708         p->csp_programs[index] = program;
0709     }
0710     return snd_sb_csp_load(p, program->data, program->size, flags);
0711 }
0712 
0713 /*
0714  * autoload hardware codec if necessary
0715  * return 0 if CSP is loaded and ready to run (p->running != 0)
0716  */
0717 static int snd_sb_csp_autoload(struct snd_sb_csp * p, snd_pcm_format_t pcm_sfmt, int play_rec_mode)
0718 {
0719     unsigned long flags;
0720     int err = 0;
0721 
0722     /* if CSP is running or manually loaded then exit */
0723     if (p->running & (SNDRV_SB_CSP_ST_RUNNING | SNDRV_SB_CSP_ST_LOADED)) 
0724         return -EBUSY;
0725 
0726     /* autoload microcode only if requested hardware codec is not already loaded */
0727     if (((1U << (__force int)pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) {
0728         p->running = SNDRV_SB_CSP_ST_AUTO;
0729     } else {
0730         switch (pcm_sfmt) {
0731         case SNDRV_PCM_FORMAT_MU_LAW:
0732             err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0);
0733             p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
0734             p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
0735             break;
0736         case SNDRV_PCM_FORMAT_A_LAW:
0737             err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0);
0738             p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
0739             p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
0740             break;
0741         case SNDRV_PCM_FORMAT_IMA_ADPCM:
0742             err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT,
0743                                SNDRV_SB_CSP_LOAD_INITBLOCK);
0744             if (err)
0745                 break;
0746             if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) {
0747                 err = snd_sb_csp_firmware_load
0748                     (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0);
0749                 p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE;
0750             } else {
0751                 err = snd_sb_csp_firmware_load
0752                     (p, CSP_PROGRAM_ADPCM_CAPTURE, 0);
0753                 p->mode = SNDRV_SB_CSP_MODE_DSP_READ;
0754             }
0755             p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
0756             break;                
0757         default:
0758             /* Decouple CSP from IRQ and DMAREQ lines */
0759             if (p->running & SNDRV_SB_CSP_ST_AUTO) {
0760                 spin_lock_irqsave(&p->chip->reg_lock, flags);
0761                 set_mode_register(p->chip, 0xfc);
0762                 set_mode_register(p->chip, 0x00);
0763                 spin_unlock_irqrestore(&p->chip->reg_lock, flags);
0764                 p->running = 0;         /* clear autoloaded flag */
0765             }
0766             return -EINVAL;
0767         }
0768         if (err) {
0769             p->acc_format = 0;
0770             p->acc_channels = p->acc_width = p->acc_rates = 0;
0771 
0772             p->running = 0;             /* clear autoloaded flag */
0773             p->mode = 0;
0774             return (err);
0775         } else {
0776             p->running = SNDRV_SB_CSP_ST_AUTO;  /* set autoloaded flag */
0777             p->acc_width = SNDRV_SB_CSP_SAMPLE_16BIT;   /* only 16 bit data */
0778             p->acc_channels = SNDRV_SB_CSP_MONO | SNDRV_SB_CSP_STEREO;
0779             p->acc_rates = SNDRV_SB_CSP_RATE_ALL;   /* HW codecs accept all rates */
0780         }   
0781 
0782     }
0783     return (p->running & SNDRV_SB_CSP_ST_AUTO) ? 0 : -ENXIO;
0784 }
0785 
0786 /*
0787  * start CSP
0788  */
0789 static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels)
0790 {
0791     unsigned char s_type;   /* sample type */
0792     unsigned char mixL, mixR;
0793     int result = -EIO;
0794     unsigned long flags;
0795 
0796     if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
0797         snd_printd("%s: Microcode not loaded\n", __func__);
0798         return -ENXIO;
0799     }
0800     if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
0801         snd_printd("%s: CSP already running\n", __func__);
0802         return -EBUSY;
0803     }
0804     if (!(sample_width & p->acc_width)) {
0805         snd_printd("%s: Unsupported PCM sample width\n", __func__);
0806         return -EINVAL;
0807     }
0808     if (!(channels & p->acc_channels)) {
0809         snd_printd("%s: Invalid number of channels\n", __func__);
0810         return -EINVAL;
0811     }
0812 
0813     /* Mute PCM volume */
0814     spin_lock_irqsave(&p->chip->mixer_lock, flags);
0815     mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);
0816     mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
0817     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
0818     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
0819     spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
0820 
0821     spin_lock(&p->chip->reg_lock);
0822     set_mode_register(p->chip, 0xc0);   /* c0 = STOP */
0823     set_mode_register(p->chip, 0x70);   /* 70 = RUN */
0824 
0825     s_type = 0x00;
0826     if (channels == SNDRV_SB_CSP_MONO)
0827         s_type = 0x11;  /* 000n 000n    (n = 1 if mono) */
0828     if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT)
0829         s_type |= 0x22; /* 00dX 00dX    (d = 1 if 8 bit samples) */
0830 
0831     if (set_codec_parameter(p->chip, 0x81, s_type)) {
0832         snd_printd("%s: Set sample type command failed\n", __func__);
0833         goto __fail;
0834     }
0835     if (set_codec_parameter(p->chip, 0x80, 0x00)) {
0836         snd_printd("%s: Codec start command failed\n", __func__);
0837         goto __fail;
0838     }
0839     p->run_width = sample_width;
0840     p->run_channels = channels;
0841 
0842     p->running |= SNDRV_SB_CSP_ST_RUNNING;
0843 
0844     if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) {
0845         set_codec_parameter(p->chip, 0xe0, 0x01);
0846         /* enable QSound decoder */
0847         set_codec_parameter(p->chip, 0x00, 0xff);
0848         set_codec_parameter(p->chip, 0x01, 0xff);
0849         p->running |= SNDRV_SB_CSP_ST_QSOUND;
0850         /* set QSound startup value */
0851         snd_sb_csp_qsound_transfer(p);
0852     }
0853     result = 0;
0854 
0855       __fail:
0856     spin_unlock(&p->chip->reg_lock);
0857 
0858     /* restore PCM volume */
0859     spin_lock_irqsave(&p->chip->mixer_lock, flags);
0860     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
0861     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
0862     spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
0863 
0864     return result;
0865 }
0866 
0867 /*
0868  * stop CSP
0869  */
0870 static int snd_sb_csp_stop(struct snd_sb_csp * p)
0871 {
0872     int result;
0873     unsigned char mixL, mixR;
0874     unsigned long flags;
0875 
0876     if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))
0877         return 0;
0878 
0879     /* Mute PCM volume */
0880     spin_lock_irqsave(&p->chip->mixer_lock, flags);
0881     mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);
0882     mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
0883     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
0884     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
0885     spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
0886 
0887     spin_lock(&p->chip->reg_lock);
0888     if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
0889         set_codec_parameter(p->chip, 0xe0, 0x01);
0890         /* disable QSound decoder */
0891         set_codec_parameter(p->chip, 0x00, 0x00);
0892         set_codec_parameter(p->chip, 0x01, 0x00);
0893 
0894         p->running &= ~SNDRV_SB_CSP_ST_QSOUND;
0895     }
0896     result = set_mode_register(p->chip, 0xc0);  /* c0 = STOP */
0897     spin_unlock(&p->chip->reg_lock);
0898 
0899     /* restore PCM volume */
0900     spin_lock_irqsave(&p->chip->mixer_lock, flags);
0901     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
0902     snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
0903     spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
0904 
0905     if (!(result))
0906         p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING);
0907     return result;
0908 }
0909 
0910 /*
0911  * pause CSP codec and hold DMA transfer
0912  */
0913 static int snd_sb_csp_pause(struct snd_sb_csp * p)
0914 {
0915     int result;
0916     unsigned long flags;
0917 
0918     if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))
0919         return -EBUSY;
0920 
0921     spin_lock_irqsave(&p->chip->reg_lock, flags);
0922     result = set_codec_parameter(p->chip, 0x80, 0xff);
0923     spin_unlock_irqrestore(&p->chip->reg_lock, flags);
0924     if (!(result))
0925         p->running |= SNDRV_SB_CSP_ST_PAUSED;
0926 
0927     return result;
0928 }
0929 
0930 /*
0931  * restart CSP codec and resume DMA transfer
0932  */
0933 static int snd_sb_csp_restart(struct snd_sb_csp * p)
0934 {
0935     int result;
0936     unsigned long flags;
0937 
0938     if (!(p->running & SNDRV_SB_CSP_ST_PAUSED))
0939         return -EBUSY;
0940 
0941     spin_lock_irqsave(&p->chip->reg_lock, flags);
0942     result = set_codec_parameter(p->chip, 0x80, 0x00);
0943     spin_unlock_irqrestore(&p->chip->reg_lock, flags);
0944     if (!(result))
0945         p->running &= ~SNDRV_SB_CSP_ST_PAUSED;
0946 
0947     return result;
0948 }
0949 
0950 /* ------------------------------ */
0951 
0952 /*
0953  * QSound mixer control for PCM
0954  */
0955 
0956 #define snd_sb_qsound_switch_info   snd_ctl_boolean_mono_info
0957 
0958 static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0959 {
0960     struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
0961     
0962     ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0;
0963     return 0;
0964 }
0965 
0966 static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0967 {
0968     struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
0969     unsigned long flags;
0970     int change;
0971     unsigned char nval;
0972     
0973     nval = ucontrol->value.integer.value[0] & 0x01;
0974     spin_lock_irqsave(&p->q_lock, flags);
0975     change = p->q_enabled != nval;
0976     p->q_enabled = nval;
0977     spin_unlock_irqrestore(&p->q_lock, flags);
0978     return change;
0979 }
0980 
0981 static int snd_sb_qsound_space_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0982 {
0983     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0984     uinfo->count = 2;
0985     uinfo->value.integer.min = 0;
0986     uinfo->value.integer.max = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
0987     return 0;
0988 }
0989 
0990 static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0991 {
0992     struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
0993     unsigned long flags;
0994     
0995     spin_lock_irqsave(&p->q_lock, flags);
0996     ucontrol->value.integer.value[0] = p->qpos_left;
0997     ucontrol->value.integer.value[1] = p->qpos_right;
0998     spin_unlock_irqrestore(&p->q_lock, flags);
0999     return 0;
1000 }
1001 
1002 static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1003 {
1004     struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
1005     unsigned long flags;
1006     int change;
1007     unsigned char nval1, nval2;
1008     
1009     nval1 = ucontrol->value.integer.value[0];
1010     if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)
1011         nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
1012     nval2 = ucontrol->value.integer.value[1];
1013     if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)
1014         nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;
1015     spin_lock_irqsave(&p->q_lock, flags);
1016     change = p->qpos_left != nval1 || p->qpos_right != nval2;
1017     p->qpos_left = nval1;
1018     p->qpos_right = nval2;
1019     p->qpos_changed = change;
1020     spin_unlock_irqrestore(&p->q_lock, flags);
1021     return change;
1022 }
1023 
1024 static const struct snd_kcontrol_new snd_sb_qsound_switch = {
1025     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1026     .name = "3D Control - Switch",
1027     .info = snd_sb_qsound_switch_info,
1028     .get = snd_sb_qsound_switch_get,
1029     .put = snd_sb_qsound_switch_put
1030 };
1031 
1032 static const struct snd_kcontrol_new snd_sb_qsound_space = {
1033     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1034     .name = "3D Control - Space",
1035     .info = snd_sb_qsound_space_info,
1036     .get = snd_sb_qsound_space_get,
1037     .put = snd_sb_qsound_space_put
1038 };
1039 
1040 static int snd_sb_qsound_build(struct snd_sb_csp * p)
1041 {
1042     struct snd_card *card;
1043     struct snd_kcontrol *kctl;
1044     int err;
1045 
1046     if (snd_BUG_ON(!p))
1047         return -EINVAL;
1048 
1049     card = p->chip->card;
1050     p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2;
1051     p->qpos_changed = 0;
1052 
1053     spin_lock_init(&p->q_lock);
1054 
1055     kctl = snd_ctl_new1(&snd_sb_qsound_switch, p);
1056     err = snd_ctl_add(card, kctl);
1057     if (err < 0)
1058         goto __error;
1059     p->qsound_switch = kctl;
1060     kctl = snd_ctl_new1(&snd_sb_qsound_space, p);
1061     err = snd_ctl_add(card, kctl);
1062     if (err < 0)
1063         goto __error;
1064     p->qsound_space = kctl;
1065 
1066     return 0;
1067 
1068      __error:
1069     snd_sb_qsound_destroy(p);
1070     return err;
1071 }
1072 
1073 static void snd_sb_qsound_destroy(struct snd_sb_csp * p)
1074 {
1075     struct snd_card *card;
1076     unsigned long flags;
1077 
1078     if (snd_BUG_ON(!p))
1079         return;
1080 
1081     card = p->chip->card;   
1082     
1083     down_write(&card->controls_rwsem);
1084     if (p->qsound_switch) {
1085         snd_ctl_remove(card, p->qsound_switch);
1086         p->qsound_switch = NULL;
1087     }
1088     if (p->qsound_space) {
1089         snd_ctl_remove(card, p->qsound_space);
1090         p->qsound_space = NULL;
1091     }
1092     up_write(&card->controls_rwsem);
1093 
1094     /* cancel pending transfer of QSound parameters */
1095     spin_lock_irqsave (&p->q_lock, flags);
1096     p->qpos_changed = 0;
1097     spin_unlock_irqrestore (&p->q_lock, flags);
1098 }
1099 
1100 /*
1101  * Transfer qsound parameters to CSP,
1102  * function should be called from interrupt routine
1103  */
1104 static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p)
1105 {
1106     int err = -ENXIO;
1107 
1108     spin_lock(&p->q_lock);
1109     if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
1110         set_codec_parameter(p->chip, 0xe0, 0x01);
1111         /* left channel */
1112         set_codec_parameter(p->chip, 0x00, p->qpos_left);
1113         set_codec_parameter(p->chip, 0x02, 0x00);
1114         /* right channel */
1115         set_codec_parameter(p->chip, 0x00, p->qpos_right);
1116         set_codec_parameter(p->chip, 0x03, 0x00);
1117         err = 0;
1118     }
1119     p->qpos_changed = 0;
1120     spin_unlock(&p->q_lock);
1121     return err;
1122 }
1123 
1124 /* ------------------------------ */
1125 
1126 /*
1127  * proc interface
1128  */
1129 static int init_proc_entry(struct snd_sb_csp * p, int device)
1130 {
1131     char name[16];
1132 
1133     sprintf(name, "cspD%d", device);
1134     snd_card_ro_proc_new(p->chip->card, name, p, info_read);
1135     return 0;
1136 }
1137 
1138 static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
1139 {
1140     struct snd_sb_csp *p = entry->private_data;
1141 
1142     snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
1143     snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
1144             ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'),
1145             ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'),
1146             ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-'));
1147     if (p->running & SNDRV_SB_CSP_ST_LOADED) {
1148         snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr);
1149         snd_iprintf(buffer, "Sample rates: ");
1150         if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) {
1151             snd_iprintf(buffer, "All\n");
1152         } else {
1153             snd_iprintf(buffer, "%s%s%s%s\n",
1154                     ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""),
1155                     ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""),
1156                     ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""),
1157                     ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : ""));
1158         }
1159         if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {
1160             snd_iprintf(buffer, "QSound decoder %sabled\n",
1161                     p->q_enabled ? "en" : "dis");
1162         } else {
1163             snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n",
1164                     p->acc_format,
1165                     ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"),
1166                     ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"),
1167                     ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"),
1168                     ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"),
1169                     ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"),
1170                     ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-"));
1171         }
1172     }
1173     if (p->running & SNDRV_SB_CSP_ST_AUTO) {
1174         snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n");
1175     }
1176     if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
1177         snd_iprintf(buffer, "Processing %dbit %s PCM samples\n",
1178                 ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8),
1179                 ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo"));
1180     }
1181     if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
1182         snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n",
1183                 p->qpos_left, p->qpos_right);
1184     }
1185 }
1186 
1187 /* */
1188 
1189 EXPORT_SYMBOL(snd_sb_csp_new);