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