linux/sound/pci/cs46xx/cs46xx_lib.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   3 *                   Abramo Bagnara <abramo@alsa-project.org>
   4 *                   Cirrus Logic, Inc.
   5 *  Routines for control of Cirrus Logic CS461x chips
   6 *
   7 *  KNOWN BUGS:
   8 *    - Sometimes the SPDIF input DSP tasks get's unsynchronized
   9 *      and the SPDIF get somewhat "distorcionated", or/and left right channel
  10 *      are swapped. To get around this problem when it happens, mute and unmute 
  11 *      the SPDIF input mixer control.
  12 *    - On the Hercules Game Theater XP the amplifier are sometimes turned
  13 *      off on inadecuate moments which causes distorcions on sound.
  14 *
  15 *  TODO:
  16 *    - Secondary CODEC on some soundcards
  17 *    - SPDIF input support for other sample rates then 48khz
  18 *    - Posibility to mix the SPDIF output with analog sources.
  19 *    - PCM channels for Center and LFE on secondary codec
  20 *
  21 *  NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which
  22 *        is default configuration), no SPDIF, no secondary codec, no
  23 *        multi channel PCM.  But known to work.
  24 *
  25 *  FINALLY: A credit to the developers Tom and Jordan 
  26 *           at Cirrus for have helping me out with the DSP, however we
  27 *           still don't have sufficient documentation and technical
  28 *           references to be able to implement all fancy feutures
  29 *           supported by the cs46xx DSP's. 
  30 *           Benny <benny@hostmobility.com>
  31 *                
  32 *   This program is free software; you can redistribute it and/or modify
  33 *   it under the terms of the GNU General Public License as published by
  34 *   the Free Software Foundation; either version 2 of the License, or
  35 *   (at your option) any later version.
  36 *
  37 *   This program is distributed in the hope that it will be useful,
  38 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  39 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40 *   GNU General Public License for more details.
  41 *
  42 *   You should have received a copy of the GNU General Public License
  43 *   along with this program; if not, write to the Free Software
  44 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  45 *
  46 */
  47
  48#include <linux/delay.h>
  49#include <linux/pci.h>
  50#include <linux/pm.h>
  51#include <linux/init.h>
  52#include <linux/interrupt.h>
  53#include <linux/slab.h>
  54#include <linux/gameport.h>
  55#include <linux/mutex.h>
  56
  57
  58#include <sound/core.h>
  59#include <sound/control.h>
  60#include <sound/info.h>
  61#include <sound/pcm.h>
  62#include <sound/pcm_params.h>
  63#include <sound/cs46xx.h>
  64
  65#include <asm/io.h>
  66
  67#include "cs46xx_lib.h"
  68#include "dsp_spos.h"
  69
  70static void amp_voyetra(struct snd_cs46xx *chip, int change);
  71
  72#ifdef CONFIG_SND_CS46XX_NEW_DSP
  73static struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
  74static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
  75static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
  76static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
  77static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
  78static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
  79#endif
  80
  81static struct snd_pcm_ops snd_cs46xx_playback_ops;
  82static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
  83static struct snd_pcm_ops snd_cs46xx_capture_ops;
  84static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
  85
  86static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,
  87                                            unsigned short reg,
  88                                            int codec_index)
  89{
  90        int count;
  91        unsigned short result,tmp;
  92        u32 offset = 0;
  93        snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
  94                     (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
  95                     return -EINVAL);
  96
  97        chip->active_ctrl(chip, 1);
  98
  99        if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
 100                offset = CS46XX_SECONDARY_CODEC_OFFSET;
 101
 102        /*
 103         *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
 104         *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97 
 105         *  3. Write ACCTL = Control Register = 460h for initiating the write7---55
 106         *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
 107         *  5. if DCV not cleared, break and return error
 108         *  6. Read ACSTS = Status Register = 464h, check VSTS bit
 109         */
 110
 111        snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
 112
 113        tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL);
 114        if ((tmp & ACCTL_VFRM) == 0) {
 115                snd_printk(KERN_WARNING  "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp);
 116                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM );
 117                msleep(50);
 118                tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset);
 119                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM );
 120
 121        }
 122
 123        /*
 124         *  Setup the AC97 control registers on the CS461x to send the
 125         *  appropriate command to the AC97 to perform the read.
 126         *  ACCAD = Command Address Register = 46Ch
 127         *  ACCDA = Command Data Register = 470h
 128         *  ACCTL = Control Register = 460h
 129         *  set DCV - will clear when process completed
 130         *  set CRW - Read command
 131         *  set VFRM - valid frame enabled
 132         *  set ESYN - ASYNC generation enabled
 133         *  set RSTN - ARST# inactive, AC97 codec not reset
 134         */
 135
 136        snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg);
 137        snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0);
 138        if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
 139                snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW | 
 140                                   ACCTL_VFRM | ACCTL_ESYN |
 141                                   ACCTL_RSTN);
 142                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
 143                                   ACCTL_VFRM | ACCTL_ESYN |
 144                                   ACCTL_RSTN);
 145        } else {
 146                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
 147                                   ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN |
 148                                   ACCTL_RSTN);
 149        }
 150
 151        /*
 152         *  Wait for the read to occur.
 153         */
 154        for (count = 0; count < 1000; count++) {
 155                /*
 156                 *  First, we want to wait for a short time.
 157                 */
 158                udelay(10);
 159                /*
 160                 *  Now, check to see if the read has completed.
 161                 *  ACCTL = 460h, DCV should be reset by now and 460h = 17h
 162                 */
 163                if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV))
 164                        goto ok1;
 165        }
 166
 167        snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg);
 168        result = 0xffff;
 169        goto end;
 170        
 171 ok1:
 172        /*
 173         *  Wait for the valid status bit to go active.
 174         */
 175        for (count = 0; count < 100; count++) {
 176                /*
 177                 *  Read the AC97 status register.
 178                 *  ACSTS = Status Register = 464h
 179                 *  VSTS - Valid Status
 180                 */
 181                if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS)
 182                        goto ok2;
 183                udelay(10);
 184        }
 185        
 186        snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg);
 187        result = 0xffff;
 188        goto end;
 189
 190 ok2:
 191        /*
 192         *  Read the data returned from the AC97 register.
 193         *  ACSDA = Status Data Register = 474h
 194         */
 195#if 0
 196        printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
 197                        snd_cs46xx_peekBA0(chip, BA0_ACSDA),
 198                        snd_cs46xx_peekBA0(chip, BA0_ACCAD));
 199#endif
 200
 201        //snd_cs46xx_peekBA0(chip, BA0_ACCAD);
 202        result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
 203 end:
 204        chip->active_ctrl(chip, -1);
 205        return result;
 206}
 207
 208static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97,
 209                                            unsigned short reg)
 210{
 211        struct snd_cs46xx *chip = ac97->private_data;
 212        unsigned short val;
 213        int codec_index = ac97->num;
 214
 215        snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
 216                   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
 217                   return 0xffff);
 218
 219        val = snd_cs46xx_codec_read(chip, reg, codec_index);
 220
 221        return val;
 222}
 223
 224
 225static void snd_cs46xx_codec_write(struct snd_cs46xx *chip,
 226                                   unsigned short reg,
 227                                   unsigned short val,
 228                                   int codec_index)
 229{
 230        int count;
 231
 232        snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
 233                    (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
 234                    return);
 235
 236        chip->active_ctrl(chip, 1);
 237
 238        /*
 239         *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
 240         *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
 241         *  3. Write ACCTL = Control Register = 460h for initiating the write
 242         *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
 243         *  5. if DCV not cleared, break and return error
 244         */
 245
 246        /*
 247         *  Setup the AC97 control registers on the CS461x to send the
 248         *  appropriate command to the AC97 to perform the read.
 249         *  ACCAD = Command Address Register = 46Ch
 250         *  ACCDA = Command Data Register = 470h
 251         *  ACCTL = Control Register = 460h
 252         *  set DCV - will clear when process completed
 253         *  reset CRW - Write command
 254         *  set VFRM - valid frame enabled
 255         *  set ESYN - ASYNC generation enabled
 256         *  set RSTN - ARST# inactive, AC97 codec not reset
 257         */
 258        snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg);
 259        snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val);
 260        snd_cs46xx_peekBA0(chip, BA0_ACCTL);
 261
 262        if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
 263                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM |
 264                                   ACCTL_ESYN | ACCTL_RSTN);
 265                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
 266                                   ACCTL_ESYN | ACCTL_RSTN);
 267        } else {
 268                snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
 269                                   ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
 270        }
 271
 272        for (count = 0; count < 4000; count++) {
 273                /*
 274                 *  First, we want to wait for a short time.
 275                 */
 276                udelay(10);
 277                /*
 278                 *  Now, check to see if the write has completed.
 279                 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
 280                 */
 281                if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
 282                        goto end;
 283                }
 284        }
 285        snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
 286 end:
 287        chip->active_ctrl(chip, -1);
 288}
 289
 290static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97,
 291                                   unsigned short reg,
 292                                   unsigned short val)
 293{
 294        struct snd_cs46xx *chip = ac97->private_data;
 295        int codec_index = ac97->num;
 296
 297        snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
 298                   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
 299                   return);
 300
 301        snd_cs46xx_codec_write(chip, reg, val, codec_index);
 302}
 303
 304
 305/*
 306 *  Chip initialization
 307 */
 308
 309int snd_cs46xx_download(struct snd_cs46xx *chip,
 310                        u32 *src,
 311                        unsigned long offset,
 312                        unsigned long len)
 313{
 314        void __iomem *dst;
 315        unsigned int bank = offset >> 16;
 316        offset = offset & 0xffff;
 317
 318        snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
 319        dst = chip->region.idx[bank+1].remap_addr + offset;
 320        len /= sizeof(u32);
 321
 322        /* writel already converts 32-bit value to right endianess */
 323        while (len-- > 0) {
 324                writel(*src++, dst);
 325                dst += sizeof(u32);
 326        }
 327        return 0;
 328}
 329
 330#ifdef CONFIG_SND_CS46XX_NEW_DSP
 331
 332#include "imgs/cwc4630.h"
 333#include "imgs/cwcasync.h"
 334#include "imgs/cwcsnoop.h"
 335#include "imgs/cwcbinhack.h"
 336#include "imgs/cwcdma.h"
 337
 338int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
 339                         unsigned long offset,
 340                         unsigned long len) 
 341{
 342        void __iomem *dst;
 343        unsigned int bank = offset >> 16;
 344        offset = offset & 0xffff;
 345
 346        snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
 347        dst = chip->region.idx[bank+1].remap_addr + offset;
 348        len /= sizeof(u32);
 349
 350        /* writel already converts 32-bit value to right endianess */
 351        while (len-- > 0) {
 352                writel(0, dst);
 353                dst += sizeof(u32);
 354        }
 355        return 0;
 356}
 357
 358#else /* old DSP image */
 359
 360#include "cs46xx_image.h"
 361
 362int snd_cs46xx_download_image(struct snd_cs46xx *chip)
 363{
 364        int idx, err;
 365        unsigned long offset = 0;
 366
 367        for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
 368                if ((err = snd_cs46xx_download(chip,
 369                                               &BA1Struct.map[offset],
 370                                               BA1Struct.memory[idx].offset,
 371                                               BA1Struct.memory[idx].size)) < 0)
 372                        return err;
 373                offset += BA1Struct.memory[idx].size >> 2;
 374        }       
 375        return 0;
 376}
 377#endif /* CONFIG_SND_CS46XX_NEW_DSP */
 378
 379/*
 380 *  Chip reset
 381 */
 382
 383static void snd_cs46xx_reset(struct snd_cs46xx *chip)
 384{
 385        int idx;
 386
 387        /*
 388         *  Write the reset bit of the SP control register.
 389         */
 390        snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP);
 391
 392        /*
 393         *  Write the control register.
 394         */
 395        snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN);
 396
 397        /*
 398         *  Clear the trap registers.
 399         */
 400        for (idx = 0; idx < 8; idx++) {
 401                snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
 402                snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF);
 403        }
 404        snd_cs46xx_poke(chip, BA1_DREG, 0);
 405
 406        /*
 407         *  Set the frame timer to reflect the number of cycles per frame.
 408         */
 409        snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
 410}
 411
 412static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) 
 413{
 414        u32 i, status = 0;
 415        /*
 416         * Make sure the previous FIFO write operation has completed.
 417         */
 418        for(i = 0; i < 50; i++){
 419                status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
 420    
 421                if( !(status & SERBST_WBSY) )
 422                        break;
 423
 424                mdelay(retry_timeout);
 425        }
 426  
 427        if(status & SERBST_WBSY) {
 428                snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n");
 429
 430                return -EINVAL;
 431        }
 432
 433        return 0;
 434}
 435
 436static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip)
 437{
 438        int idx, powerdown = 0;
 439        unsigned int tmp;
 440
 441        /*
 442         *  See if the devices are powered down.  If so, we must power them up first
 443         *  or they will not respond.
 444         */
 445        tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
 446        if (!(tmp & CLKCR1_SWCE)) {
 447                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
 448                powerdown = 1;
 449        }
 450
 451        /*
 452         *  We want to clear out the serial port FIFOs so we don't end up playing
 453         *  whatever random garbage happens to be in them.  We fill the sample FIFOS
 454         *  with zero (silence).
 455         */
 456        snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0);
 457
 458        /*
 459         *  Fill all 256 sample FIFO locations.
 460         */
 461        for (idx = 0; idx < 0xFF; idx++) {
 462                /*
 463                 *  Make sure the previous FIFO write operation has completed.
 464                 */
 465                if (cs46xx_wait_for_fifo(chip,1)) {
 466                        snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx);
 467
 468                        if (powerdown)
 469                                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
 470          
 471                        break;
 472                }
 473                /*
 474                 *  Write the serial port FIFO index.
 475                 */
 476                snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
 477                /*
 478                 *  Tell the serial port to load the new value into the FIFO location.
 479                 */
 480                snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
 481        }
 482        /*
 483         *  Now, if we powered up the devices, then power them back down again.
 484         *  This is kinda ugly, but should never happen.
 485         */
 486        if (powerdown)
 487                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
 488}
 489
 490static void snd_cs46xx_proc_start(struct snd_cs46xx *chip)
 491{
 492        int cnt;
 493
 494        /*
 495         *  Set the frame timer to reflect the number of cycles per frame.
 496         */
 497        snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
 498        /*
 499         *  Turn on the run, run at frame, and DMA enable bits in the local copy of
 500         *  the SP control register.
 501         */
 502        snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
 503        /*
 504         *  Wait until the run at frame bit resets itself in the SP control
 505         *  register.
 506         */
 507        for (cnt = 0; cnt < 25; cnt++) {
 508                udelay(50);
 509                if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR))
 510                        break;
 511        }
 512
 513        if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)
 514                snd_printk(KERN_ERR "SPCR_RUNFR never reset\n");
 515}
 516
 517static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip)
 518{
 519        /*
 520         *  Turn off the run, run at frame, and DMA enable bits in the local copy of
 521         *  the SP control register.
 522         */
 523        snd_cs46xx_poke(chip, BA1_SPCR, 0);
 524}
 525
 526/*
 527 *  Sample rate routines
 528 */
 529
 530#define GOF_PER_SEC 200
 531
 532static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
 533{
 534        unsigned long flags;
 535        unsigned int tmp1, tmp2;
 536        unsigned int phiIncr;
 537        unsigned int correctionPerGOF, correctionPerSec;
 538
 539        /*
 540         *  Compute the values used to drive the actual sample rate conversion.
 541         *  The following formulas are being computed, using inline assembly
 542         *  since we need to use 64 bit arithmetic to compute the values:
 543         *
 544         *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
 545         *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
 546         *                                   GOF_PER_SEC)
 547         *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
 548         *                       GOF_PER_SEC * correctionPerGOF
 549         *
 550         *  i.e.
 551         *
 552         *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
 553         *  correctionPerGOF:correctionPerSec =
 554         *      dividend:remainder(ulOther / GOF_PER_SEC)
 555         */
 556        tmp1 = rate << 16;
 557        phiIncr = tmp1 / 48000;
 558        tmp1 -= phiIncr * 48000;
 559        tmp1 <<= 10;
 560        phiIncr <<= 10;
 561        tmp2 = tmp1 / 48000;
 562        phiIncr += tmp2;
 563        tmp1 -= tmp2 * 48000;
 564        correctionPerGOF = tmp1 / GOF_PER_SEC;
 565        tmp1 -= correctionPerGOF * GOF_PER_SEC;
 566        correctionPerSec = tmp1;
 567
 568        /*
 569         *  Fill in the SampleRateConverter control block.
 570         */
 571        spin_lock_irqsave(&chip->reg_lock, flags);
 572        snd_cs46xx_poke(chip, BA1_PSRC,
 573          ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
 574        snd_cs46xx_poke(chip, BA1_PPI, phiIncr);
 575        spin_unlock_irqrestore(&chip->reg_lock, flags);
 576}
 577
 578static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
 579{
 580        unsigned long flags;
 581        unsigned int phiIncr, coeffIncr, tmp1, tmp2;
 582        unsigned int correctionPerGOF, correctionPerSec, initialDelay;
 583        unsigned int frameGroupLength, cnt;
 584
 585        /*
 586         *  We can only decimate by up to a factor of 1/9th the hardware rate.
 587         *  Correct the value if an attempt is made to stray outside that limit.
 588         */
 589        if ((rate * 9) < 48000)
 590                rate = 48000 / 9;
 591
 592        /*
 593         *  We can not capture at at rate greater than the Input Rate (48000).
 594         *  Return an error if an attempt is made to stray outside that limit.
 595         */
 596        if (rate > 48000)
 597                rate = 48000;
 598
 599        /*
 600         *  Compute the values used to drive the actual sample rate conversion.
 601         *  The following formulas are being computed, using inline assembly
 602         *  since we need to use 64 bit arithmetic to compute the values:
 603         *
 604         *     coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
 605         *     phiIncr = floor((Fs,in * 2^26) / Fs,out)
 606         *     correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
 607         *                                GOF_PER_SEC)
 608         *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
 609         *                          GOF_PER_SEC * correctionPerGOF
 610         *     initialDelay = ceil((24 * Fs,in) / Fs,out)
 611         *
 612         * i.e.
 613         *
 614         *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
 615         *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
 616         *     correctionPerGOF:correctionPerSec =
 617         *          dividend:remainder(ulOther / GOF_PER_SEC)
 618         *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
 619         */
 620
 621        tmp1 = rate << 16;
 622        coeffIncr = tmp1 / 48000;
 623        tmp1 -= coeffIncr * 48000;
 624        tmp1 <<= 7;
 625        coeffIncr <<= 7;
 626        coeffIncr += tmp1 / 48000;
 627        coeffIncr ^= 0xFFFFFFFF;
 628        coeffIncr++;
 629        tmp1 = 48000 << 16;
 630        phiIncr = tmp1 / rate;
 631        tmp1 -= phiIncr * rate;
 632        tmp1 <<= 10;
 633        phiIncr <<= 10;
 634        tmp2 = tmp1 / rate;
 635        phiIncr += tmp2;
 636        tmp1 -= tmp2 * rate;
 637        correctionPerGOF = tmp1 / GOF_PER_SEC;
 638        tmp1 -= correctionPerGOF * GOF_PER_SEC;
 639        correctionPerSec = tmp1;
 640        initialDelay = ((48000 * 24) + rate - 1) / rate;
 641
 642        /*
 643         *  Fill in the VariDecimate control block.
 644         */
 645        spin_lock_irqsave(&chip->reg_lock, flags);
 646        snd_cs46xx_poke(chip, BA1_CSRC,
 647                ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
 648        snd_cs46xx_poke(chip, BA1_CCI, coeffIncr);
 649        snd_cs46xx_poke(chip, BA1_CD,
 650                (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
 651        snd_cs46xx_poke(chip, BA1_CPI, phiIncr);
 652        spin_unlock_irqrestore(&chip->reg_lock, flags);
 653
 654        /*
 655         *  Figure out the frame group length for the write back task.  Basically,
 656         *  this is just the factors of 24000 (2^6*3*5^3) that are not present in
 657         *  the output sample rate.
 658         */
 659        frameGroupLength = 1;
 660        for (cnt = 2; cnt <= 64; cnt *= 2) {
 661                if (((rate / cnt) * cnt) != rate)
 662                        frameGroupLength *= 2;
 663        }
 664        if (((rate / 3) * 3) != rate) {
 665                frameGroupLength *= 3;
 666        }
 667        for (cnt = 5; cnt <= 125; cnt *= 5) {
 668                if (((rate / cnt) * cnt) != rate) 
 669                        frameGroupLength *= 5;
 670        }
 671
 672        /*
 673         * Fill in the WriteBack control block.
 674         */
 675        spin_lock_irqsave(&chip->reg_lock, flags);
 676        snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength);
 677        snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength));
 678        snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF);
 679        snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000));
 680        snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF);
 681        spin_unlock_irqrestore(&chip->reg_lock, flags);
 682}
 683
 684/*
 685 *  PCM part
 686 */
 687
 688static void snd_cs46xx_pb_trans_copy(struct snd_pcm_substream *substream,
 689                                     struct snd_pcm_indirect *rec, size_t bytes)
 690{
 691        struct snd_pcm_runtime *runtime = substream->runtime;
 692        struct snd_cs46xx_pcm * cpcm = runtime->private_data;
 693        memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
 694}
 695
 696static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream)
 697{
 698        struct snd_pcm_runtime *runtime = substream->runtime;
 699        struct snd_cs46xx_pcm * cpcm = runtime->private_data;
 700        snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
 701        return 0;
 702}
 703
 704static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream,
 705                                     struct snd_pcm_indirect *rec, size_t bytes)
 706{
 707        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 708        struct snd_pcm_runtime *runtime = substream->runtime;
 709        memcpy(runtime->dma_area + rec->sw_data,
 710               chip->capt.hw_buf.area + rec->hw_data, bytes);
 711}
 712
 713static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream)
 714{
 715        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 716        snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
 717        return 0;
 718}
 719
 720static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream)
 721{
 722        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 723        size_t ptr;
 724        struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
 725        snd_assert (cpcm->pcm_channel,return -ENXIO);
 726
 727#ifdef CONFIG_SND_CS46XX_NEW_DSP
 728        ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
 729#else
 730        ptr = snd_cs46xx_peek(chip, BA1_PBA);
 731#endif
 732        ptr -= cpcm->hw_buf.addr;
 733        return ptr >> cpcm->shift;
 734}
 735
 736static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_substream *substream)
 737{
 738        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 739        size_t ptr;
 740        struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
 741
 742#ifdef CONFIG_SND_CS46XX_NEW_DSP
 743        snd_assert (cpcm->pcm_channel,return -ENXIO);
 744        ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
 745#else
 746        ptr = snd_cs46xx_peek(chip, BA1_PBA);
 747#endif
 748        ptr -= cpcm->hw_buf.addr;
 749        return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
 750}
 751
 752static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(struct snd_pcm_substream *substream)
 753{
 754        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 755        size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
 756        return ptr >> chip->capt.shift;
 757}
 758
 759static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(struct snd_pcm_substream *substream)
 760{
 761        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 762        size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
 763        return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
 764}
 765
 766static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream,
 767                                       int cmd)
 768{
 769        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 770        /*struct snd_pcm_runtime *runtime = substream->runtime;*/
 771        int result = 0;
 772
 773#ifdef CONFIG_SND_CS46XX_NEW_DSP
 774        struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
 775        if (! cpcm->pcm_channel) {
 776                return -ENXIO;
 777        }
 778#endif
 779        switch (cmd) {
 780        case SNDRV_PCM_TRIGGER_START:
 781        case SNDRV_PCM_TRIGGER_RESUME:
 782#ifdef CONFIG_SND_CS46XX_NEW_DSP
 783                /* magic value to unmute PCM stream  playback volume */
 784                snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 
 785                                       SCBVolumeCtrl) << 2, 0x80008000);
 786
 787                if (cpcm->pcm_channel->unlinked)
 788                        cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
 789
 790                if (substream->runtime->periods != CS46XX_FRAGS)
 791                        snd_cs46xx_playback_transfer(substream);
 792#else
 793                spin_lock(&chip->reg_lock);
 794                if (substream->runtime->periods != CS46XX_FRAGS)
 795                        snd_cs46xx_playback_transfer(substream);
 796                { unsigned int tmp;
 797                tmp = snd_cs46xx_peek(chip, BA1_PCTL);
 798                tmp &= 0x0000ffff;
 799                snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
 800                }
 801                spin_unlock(&chip->reg_lock);
 802#endif
 803                break;
 804        case SNDRV_PCM_TRIGGER_STOP:
 805        case SNDRV_PCM_TRIGGER_SUSPEND:
 806#ifdef CONFIG_SND_CS46XX_NEW_DSP
 807                /* magic mute channel */
 808                snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 
 809                                       SCBVolumeCtrl) << 2, 0xffffffff);
 810
 811                if (!cpcm->pcm_channel->unlinked)
 812                        cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
 813#else
 814                spin_lock(&chip->reg_lock);
 815                { unsigned int tmp;
 816                tmp = snd_cs46xx_peek(chip, BA1_PCTL);
 817                tmp &= 0x0000ffff;
 818                snd_cs46xx_poke(chip, BA1_PCTL, tmp);
 819                }
 820                spin_unlock(&chip->reg_lock);
 821#endif
 822                break;
 823        default:
 824                result = -EINVAL;
 825                break;
 826        }
 827
 828        return result;
 829}
 830
 831static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream,
 832                                      int cmd)
 833{
 834        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 835        unsigned int tmp;
 836        int result = 0;
 837
 838        spin_lock(&chip->reg_lock);
 839        switch (cmd) {
 840        case SNDRV_PCM_TRIGGER_START:
 841        case SNDRV_PCM_TRIGGER_RESUME:
 842                tmp = snd_cs46xx_peek(chip, BA1_CCTL);
 843                tmp &= 0xffff0000;
 844                snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp);
 845                break;
 846        case SNDRV_PCM_TRIGGER_STOP:
 847        case SNDRV_PCM_TRIGGER_SUSPEND:
 848                tmp = snd_cs46xx_peek(chip, BA1_CCTL);
 849                tmp &= 0xffff0000;
 850                snd_cs46xx_poke(chip, BA1_CCTL, tmp);
 851                break;
 852        default:
 853                result = -EINVAL;
 854                break;
 855        }
 856        spin_unlock(&chip->reg_lock);
 857
 858        return result;
 859}
 860
 861#ifdef CONFIG_SND_CS46XX_NEW_DSP
 862static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46xx_pcm *cpcm,
 863                                       int sample_rate) 
 864{
 865
 866        /* If PCMReaderSCB and SrcTaskSCB not created yet ... */
 867        if ( cpcm->pcm_channel == NULL) {
 868                cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, 
 869                                                                   cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id);
 870                if (cpcm->pcm_channel == NULL) {
 871                        snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");
 872                        return -ENOMEM;
 873                }
 874                cpcm->pcm_channel->sample_rate = sample_rate;
 875        } else
 876        /* if sample rate is changed */
 877        if ((int)cpcm->pcm_channel->sample_rate != sample_rate) {
 878                int unlinked = cpcm->pcm_channel->unlinked;
 879                cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
 880
 881                if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, 
 882                                                                         cpcm->hw_buf.addr,
 883                                                                         cpcm->pcm_channel_id)) == NULL) {
 884                        snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
 885                        return -ENOMEM;
 886                }
 887
 888                if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
 889                cpcm->pcm_channel->sample_rate = sample_rate;
 890        }
 891
 892        return 0;
 893}
 894#endif
 895
 896
 897static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
 898                                         struct snd_pcm_hw_params *hw_params)
 899{
 900        struct snd_pcm_runtime *runtime = substream->runtime;
 901        struct snd_cs46xx_pcm *cpcm;
 902        int err;
 903#ifdef CONFIG_SND_CS46XX_NEW_DSP
 904        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
 905        int sample_rate = params_rate(hw_params);
 906        int period_size = params_period_bytes(hw_params);
 907#endif
 908        cpcm = runtime->private_data;
 909
 910#ifdef CONFIG_SND_CS46XX_NEW_DSP
 911        snd_assert (sample_rate != 0, return -ENXIO);
 912
 913        mutex_lock(&chip->spos_mutex);
 914
 915        if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
 916                mutex_unlock(&chip->spos_mutex);
 917                return -ENXIO;
 918        }
 919
 920        snd_assert (cpcm->pcm_channel != NULL);
 921        if (!cpcm->pcm_channel) {
 922                mutex_unlock(&chip->spos_mutex);
 923                return -ENXIO;
 924        }
 925
 926
 927        if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) {
 928                 mutex_unlock(&chip->spos_mutex);
 929                 return -EINVAL;
 930         }
 931
 932        snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n",
 933                     period_size, params_periods(hw_params),
 934                     params_buffer_bytes(hw_params));
 935#endif
 936
 937        if (params_periods(hw_params) == CS46XX_FRAGS) {
 938                if (runtime->dma_area != cpcm->hw_buf.area)
 939                        snd_pcm_lib_free_pages(substream);
 940                runtime->dma_area = cpcm->hw_buf.area;
 941                runtime->dma_addr = cpcm->hw_buf.addr;
 942                runtime->dma_bytes = cpcm->hw_buf.bytes;
 943
 944
 945#ifdef CONFIG_SND_CS46XX_NEW_DSP
 946                if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
 947                        substream->ops = &snd_cs46xx_playback_ops;
 948                } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
 949                        substream->ops = &snd_cs46xx_playback_rear_ops;
 950                } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
 951                        substream->ops = &snd_cs46xx_playback_clfe_ops;
 952                } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
 953                        substream->ops = &snd_cs46xx_playback_iec958_ops;
 954                } else {
 955                        snd_assert(0);
 956                }
 957#else
 958                substream->ops = &snd_cs46xx_playback_ops;
 959#endif
 960
 961        } else {
 962                if (runtime->dma_area == cpcm->hw_buf.area) {
 963                        runtime->dma_area = NULL;
 964                        runtime->dma_addr = 0;
 965                        runtime->dma_bytes = 0;
 966                }
 967                if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {
 968#ifdef CONFIG_SND_CS46XX_NEW_DSP
 969                        mutex_unlock(&chip->spos_mutex);
 970#endif
 971                        return err;
 972                }
 973
 974#ifdef CONFIG_SND_CS46XX_NEW_DSP
 975                if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
 976                        substream->ops = &snd_cs46xx_playback_indirect_ops;
 977                } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
 978                        substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
 979                } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
 980                        substream->ops = &snd_cs46xx_playback_indirect_clfe_ops;
 981                } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
 982                        substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;
 983                } else {
 984                        snd_assert(0);
 985                }
 986#else
 987                substream->ops = &snd_cs46xx_playback_indirect_ops;
 988#endif
 989
 990        }
 991
 992#ifdef CONFIG_SND_CS46XX_NEW_DSP
 993        mutex_unlock(&chip->spos_mutex);
 994#endif
 995
 996        return 0;
 997}
 998
 999static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
1000{
1001        /*struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);*/
1002        struct snd_pcm_runtime *runtime = substream->runtime;
1003        struct snd_cs46xx_pcm *cpcm;
1004
1005        cpcm = runtime->private_data;
1006
1007        /* if play_back open fails, then this function
1008           is called and cpcm can actually be NULL here */
1009        if (!cpcm) return -ENXIO;
1010
1011        if (runtime->dma_area != cpcm->hw_buf.area)
1012                snd_pcm_lib_free_pages(substream);
1013    
1014        runtime->dma_area = NULL;
1015        runtime->dma_addr = 0;
1016        runtime->dma_bytes = 0;
1017
1018        return 0;
1019}
1020
1021static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream)
1022{
1023        unsigned int tmp;
1024        unsigned int pfie;
1025        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1026        struct snd_pcm_runtime *runtime = substream->runtime;
1027        struct snd_cs46xx_pcm *cpcm;
1028
1029        cpcm = runtime->private_data;
1030
1031#ifdef CONFIG_SND_CS46XX_NEW_DSP
1032    snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
1033
1034        pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );
1035        pfie &= ~0x0000f03f;
1036#else
1037        /* old dsp */
1038        pfie = snd_cs46xx_peek(chip, BA1_PFIE);
1039        pfie &= ~0x0000f03f;
1040#endif
1041
1042        cpcm->shift = 2;
1043        /* if to convert from stereo to mono */
1044        if (runtime->channels == 1) {
1045                cpcm->shift--;
1046                pfie |= 0x00002000;
1047        }
1048        /* if to convert from 8 bit to 16 bit */
1049        if (snd_pcm_format_width(runtime->format) == 8) {
1050                cpcm->shift--;
1051                pfie |= 0x00001000;
1052        }
1053        /* if to convert to unsigned */
1054        if (snd_pcm_format_unsigned(runtime->format))
1055                pfie |= 0x00008000;
1056
1057        /* Never convert byte order when sample stream is 8 bit */
1058        if (snd_pcm_format_width(runtime->format) != 8) {
1059                /* convert from big endian to little endian */
1060                if (snd_pcm_format_big_endian(runtime->format))
1061                        pfie |= 0x00004000;
1062        }
1063        
1064        memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
1065        cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
1066        cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
1067
1068#ifdef CONFIG_SND_CS46XX_NEW_DSP
1069
1070        tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);
1071        tmp &= ~0x000003ff;
1072        tmp |= (4 << cpcm->shift) - 1;
1073        /* playback transaction count register */
1074        snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp);
1075
1076        /* playback format && interrupt enable */
1077        snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot);
1078#else
1079        snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr);
1080        tmp = snd_cs46xx_peek(chip, BA1_PDTC);
1081        tmp &= ~0x000003ff;
1082        tmp |= (4 << cpcm->shift) - 1;
1083        snd_cs46xx_poke(chip, BA1_PDTC, tmp);
1084        snd_cs46xx_poke(chip, BA1_PFIE, pfie);
1085        snd_cs46xx_set_play_sample_rate(chip, runtime->rate);
1086#endif
1087
1088        return 0;
1089}
1090
1091static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
1092                                        struct snd_pcm_hw_params *hw_params)
1093{
1094        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1095        struct snd_pcm_runtime *runtime = substream->runtime;
1096        int err;
1097
1098#ifdef CONFIG_SND_CS46XX_NEW_DSP
1099        cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params));
1100#endif
1101        if (runtime->periods == CS46XX_FRAGS) {
1102                if (runtime->dma_area != chip->capt.hw_buf.area)
1103                        snd_pcm_lib_free_pages(substream);
1104                runtime->dma_area = chip->capt.hw_buf.area;
1105                runtime->dma_addr = chip->capt.hw_buf.addr;
1106                runtime->dma_bytes = chip->capt.hw_buf.bytes;
1107                substream->ops = &snd_cs46xx_capture_ops;
1108        } else {
1109                if (runtime->dma_area == chip->capt.hw_buf.area) {
1110                        runtime->dma_area = NULL;
1111                        runtime->dma_addr = 0;
1112                        runtime->dma_bytes = 0;
1113                }
1114                if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1115                        return err;
1116                substream->ops = &snd_cs46xx_capture_indirect_ops;
1117        }
1118
1119        return 0;
1120}
1121
1122static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
1123{
1124        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1125        struct snd_pcm_runtime *runtime = substream->runtime;
1126
1127        if (runtime->dma_area != chip->capt.hw_buf.area)
1128                snd_pcm_lib_free_pages(substream);
1129        runtime->dma_area = NULL;
1130        runtime->dma_addr = 0;
1131        runtime->dma_bytes = 0;
1132
1133        return 0;
1134}
1135
1136static int snd_cs46xx_capture_prepare(struct snd_pcm_substream *substream)
1137{
1138        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1139        struct snd_pcm_runtime *runtime = substream->runtime;
1140
1141        snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
1142        chip->capt.shift = 2;
1143        memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
1144        chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
1145        chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
1146        snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
1147
1148        return 0;
1149}
1150
1151static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id)
1152{
1153        struct snd_cs46xx *chip = dev_id;
1154        u32 status1;
1155#ifdef CONFIG_SND_CS46XX_NEW_DSP
1156        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1157        u32 status2;
1158        int i;
1159        struct snd_cs46xx_pcm *cpcm = NULL;
1160#endif
1161
1162        /*
1163         *  Read the Interrupt Status Register to clear the interrupt
1164         */
1165        status1 = snd_cs46xx_peekBA0(chip, BA0_HISR);
1166        if ((status1 & 0x7fffffff) == 0) {
1167                snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
1168                return IRQ_NONE;
1169        }
1170
1171#ifdef CONFIG_SND_CS46XX_NEW_DSP
1172        status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0);
1173
1174        for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
1175                if (i <= 15) {
1176                        if ( status1 & (1 << i) ) {
1177                                if (i == CS46XX_DSP_CAPTURE_CHANNEL) {
1178                                        if (chip->capt.substream)
1179                                                snd_pcm_period_elapsed(chip->capt.substream);
1180                                } else {
1181                                        if (ins->pcm_channels[i].active &&
1182                                            ins->pcm_channels[i].private_data &&
1183                                            !ins->pcm_channels[i].unlinked) {
1184                                                cpcm = ins->pcm_channels[i].private_data;
1185                                                snd_pcm_period_elapsed(cpcm->substream);
1186                                        }
1187                                }
1188                        }
1189                } else {
1190                        if ( status2 & (1 << (i - 16))) {
1191                                if (ins->pcm_channels[i].active && 
1192                                    ins->pcm_channels[i].private_data &&
1193                                    !ins->pcm_channels[i].unlinked) {
1194                                        cpcm = ins->pcm_channels[i].private_data;
1195                                        snd_pcm_period_elapsed(cpcm->substream);
1196                                }
1197                        }
1198                }
1199        }
1200
1201#else
1202        /* old dsp */
1203        if ((status1 & HISR_VC0) && chip->playback_pcm) {
1204                if (chip->playback_pcm->substream)
1205                        snd_pcm_period_elapsed(chip->playback_pcm->substream);
1206        }
1207        if ((status1 & HISR_VC1) && chip->pcm) {
1208                if (chip->capt.substream)
1209                        snd_pcm_period_elapsed(chip->capt.substream);
1210        }
1211#endif
1212
1213        if ((status1 & HISR_MIDI) && chip->rmidi) {
1214                unsigned char c;
1215                
1216                spin_lock(&chip->reg_lock);
1217                while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
1218                        c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
1219                        if ((chip->midcr & MIDCR_RIE) == 0)
1220                                continue;
1221                        snd_rawmidi_receive(chip->midi_input, &c, 1);
1222                }
1223                while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
1224                        if ((chip->midcr & MIDCR_TIE) == 0)
1225                                break;
1226                        if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) {
1227                                chip->midcr &= ~MIDCR_TIE;
1228                                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
1229                                break;
1230                        }
1231                        snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
1232                }
1233                spin_unlock(&chip->reg_lock);
1234        }
1235        /*
1236         *  EOI to the PCI part....reenables interrupts
1237         */
1238        snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
1239
1240        return IRQ_HANDLED;
1241}
1242
1243static struct snd_pcm_hardware snd_cs46xx_playback =
1244{
1245        .info =                 (SNDRV_PCM_INFO_MMAP |
1246                                 SNDRV_PCM_INFO_INTERLEAVED | 
1247                                 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
1248                                 /*SNDRV_PCM_INFO_RESUME*/),
1249        .formats =              (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
1250                                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
1251                                 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
1252        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1253        .rate_min =             5500,
1254        .rate_max =             48000,
1255        .channels_min =         1,
1256        .channels_max =         2,
1257        .buffer_bytes_max =     (256 * 1024),
1258        .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
1259        .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
1260        .periods_min =          CS46XX_FRAGS,
1261        .periods_max =          1024,
1262        .fifo_size =            0,
1263};
1264
1265static struct snd_pcm_hardware snd_cs46xx_capture =
1266{
1267        .info =                 (SNDRV_PCM_INFO_MMAP |
1268                                 SNDRV_PCM_INFO_INTERLEAVED |
1269                                 SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
1270                                 /*SNDRV_PCM_INFO_RESUME*/),
1271        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
1272        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1273        .rate_min =             5500,
1274        .rate_max =             48000,
1275        .channels_min =         2,
1276        .channels_max =         2,
1277        .buffer_bytes_max =     (256 * 1024),
1278        .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
1279        .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
1280        .periods_min =          CS46XX_FRAGS,
1281        .periods_max =          1024,
1282        .fifo_size =            0,
1283};
1284
1285#ifdef CONFIG_SND_CS46XX_NEW_DSP
1286
1287static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
1288
1289static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
1290        .count = ARRAY_SIZE(period_sizes),
1291        .list = period_sizes,
1292        .mask = 0
1293};
1294
1295#endif
1296
1297static void snd_cs46xx_pcm_free_substream(struct snd_pcm_runtime *runtime)
1298{
1299        kfree(runtime->private_data);
1300}
1301
1302static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,int pcm_channel_id)
1303{
1304        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1305        struct snd_cs46xx_pcm * cpcm;
1306        struct snd_pcm_runtime *runtime = substream->runtime;
1307
1308        cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL);
1309        if (cpcm == NULL)
1310                return -ENOMEM;
1311        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
1312                                PAGE_SIZE, &cpcm->hw_buf) < 0) {
1313                kfree(cpcm);
1314                return -ENOMEM;
1315        }
1316
1317        runtime->hw = snd_cs46xx_playback;
1318        runtime->private_data = cpcm;
1319        runtime->private_free = snd_cs46xx_pcm_free_substream;
1320
1321        cpcm->substream = substream;
1322#ifdef CONFIG_SND_CS46XX_NEW_DSP
1323        mutex_lock(&chip->spos_mutex);
1324        cpcm->pcm_channel = NULL; 
1325        cpcm->pcm_channel_id = pcm_channel_id;
1326
1327
1328        snd_pcm_hw_constraint_list(runtime, 0,
1329                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 
1330                                   &hw_constraints_period_sizes);
1331
1332        mutex_unlock(&chip->spos_mutex);
1333#else
1334        chip->playback_pcm = cpcm; /* HACK */
1335#endif
1336
1337        if (chip->accept_valid)
1338                substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
1339        chip->active_ctrl(chip, 1);
1340
1341        return 0;
1342}
1343
1344static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream)
1345{
1346        snd_printdd("open front channel\n");
1347        return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
1348}
1349
1350#ifdef CONFIG_SND_CS46XX_NEW_DSP
1351static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream)
1352{
1353        snd_printdd("open rear channel\n");
1354
1355        return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
1356}
1357
1358static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream)
1359{
1360        snd_printdd("open center - LFE channel\n");
1361
1362        return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);
1363}
1364
1365static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream)
1366{
1367        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1368
1369        snd_printdd("open raw iec958 channel\n");
1370
1371        mutex_lock(&chip->spos_mutex);
1372        cs46xx_iec958_pre_open (chip);
1373        mutex_unlock(&chip->spos_mutex);
1374
1375        return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
1376}
1377
1378static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream);
1379
1380static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream)
1381{
1382        int err;
1383        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1384  
1385        snd_printdd("close raw iec958 channel\n");
1386
1387        err = snd_cs46xx_playback_close(substream);
1388
1389        mutex_lock(&chip->spos_mutex);
1390        cs46xx_iec958_post_close (chip);
1391        mutex_unlock(&chip->spos_mutex);
1392
1393        return err;
1394}
1395#endif
1396
1397static int snd_cs46xx_capture_open(struct snd_pcm_substream *substream)
1398{
1399        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1400
1401        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
1402                                PAGE_SIZE, &chip->capt.hw_buf) < 0)
1403                return -ENOMEM;
1404        chip->capt.substream = substream;
1405        substream->runtime->hw = snd_cs46xx_capture;
1406
1407        if (chip->accept_valid)
1408                substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
1409
1410        chip->active_ctrl(chip, 1);
1411
1412#ifdef CONFIG_SND_CS46XX_NEW_DSP
1413        snd_pcm_hw_constraint_list(substream->runtime, 0,
1414                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 
1415                                   &hw_constraints_period_sizes);
1416#endif
1417        return 0;
1418}
1419
1420static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream)
1421{
1422        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1423        struct snd_pcm_runtime *runtime = substream->runtime;
1424        struct snd_cs46xx_pcm * cpcm;
1425
1426        cpcm = runtime->private_data;
1427
1428        /* when playback_open fails, then cpcm can be NULL */
1429        if (!cpcm) return -ENXIO;
1430
1431#ifdef CONFIG_SND_CS46XX_NEW_DSP
1432        mutex_lock(&chip->spos_mutex);
1433        if (cpcm->pcm_channel) {
1434                cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel);
1435                cpcm->pcm_channel = NULL;
1436        }
1437        mutex_unlock(&chip->spos_mutex);
1438#else
1439        chip->playback_pcm = NULL;
1440#endif
1441
1442        cpcm->substream = NULL;
1443        snd_dma_free_pages(&cpcm->hw_buf);
1444        chip->active_ctrl(chip, -1);
1445
1446        return 0;
1447}
1448
1449static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
1450{
1451        struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
1452
1453        chip->capt.substream = NULL;
1454        snd_dma_free_pages(&chip->capt.hw_buf);
1455        chip->active_ctrl(chip, -1);
1456
1457        return 0;
1458}
1459
1460#ifdef CONFIG_SND_CS46XX_NEW_DSP
1461static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
1462        .open =                 snd_cs46xx_playback_open_rear,
1463        .close =                snd_cs46xx_playback_close,
1464        .ioctl =                snd_pcm_lib_ioctl,
1465        .hw_params =            snd_cs46xx_playback_hw_params,
1466        .hw_free =              snd_cs46xx_playback_hw_free,
1467        .prepare =              snd_cs46xx_playback_prepare,
1468        .trigger =              snd_cs46xx_playback_trigger,
1469        .pointer =              snd_cs46xx_playback_direct_pointer,
1470};
1471
1472static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
1473        .open =                 snd_cs46xx_playback_open_rear,
1474        .close =                snd_cs46xx_playback_close,
1475        .ioctl =                snd_pcm_lib_ioctl,
1476        .hw_params =            snd_cs46xx_playback_hw_params,
1477        .hw_free =              snd_cs46xx_playback_hw_free,
1478        .prepare =              snd_cs46xx_playback_prepare,
1479        .trigger =              snd_cs46xx_playback_trigger,
1480        .pointer =              snd_cs46xx_playback_indirect_pointer,
1481        .ack =                  snd_cs46xx_playback_transfer,
1482};
1483
1484static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
1485        .open =                 snd_cs46xx_playback_open_clfe,
1486        .close =                snd_cs46xx_playback_close,
1487        .ioctl =                snd_pcm_lib_ioctl,
1488        .hw_params =            snd_cs46xx_playback_hw_params,
1489        .hw_free =              snd_cs46xx_playback_hw_free,
1490        .prepare =              snd_cs46xx_playback_prepare,
1491        .trigger =              snd_cs46xx_playback_trigger,
1492        .pointer =              snd_cs46xx_playback_direct_pointer,
1493};
1494
1495static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
1496        .open =                 snd_cs46xx_playback_open_clfe,
1497        .close =                snd_cs46xx_playback_close,
1498        .ioctl =                snd_pcm_lib_ioctl,
1499        .hw_params =            snd_cs46xx_playback_hw_params,
1500        .hw_free =              snd_cs46xx_playback_hw_free,
1501        .prepare =              snd_cs46xx_playback_prepare,
1502        .trigger =              snd_cs46xx_playback_trigger,
1503        .pointer =              snd_cs46xx_playback_indirect_pointer,
1504        .ack =                  snd_cs46xx_playback_transfer,
1505};
1506
1507static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
1508        .open =                 snd_cs46xx_playback_open_iec958,
1509        .close =                snd_cs46xx_playback_close_iec958,
1510        .ioctl =                snd_pcm_lib_ioctl,
1511        .hw_params =            snd_cs46xx_playback_hw_params,
1512        .hw_free =              snd_cs46xx_playback_hw_free,
1513        .prepare =              snd_cs46xx_playback_prepare,
1514        .trigger =              snd_cs46xx_playback_trigger,
1515        .pointer =              snd_cs46xx_playback_direct_pointer,
1516};
1517
1518static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
1519        .open =                 snd_cs46xx_playback_open_iec958,
1520        .close =                snd_cs46xx_playback_close_iec958,
1521        .ioctl =                snd_pcm_lib_ioctl,
1522        .hw_params =            snd_cs46xx_playback_hw_params,
1523        .hw_free =              snd_cs46xx_playback_hw_free,
1524        .prepare =              snd_cs46xx_playback_prepare,
1525        .trigger =              snd_cs46xx_playback_trigger,
1526        .pointer =              snd_cs46xx_playback_indirect_pointer,
1527        .ack =                  snd_cs46xx_playback_transfer,
1528};
1529
1530#endif
1531
1532static struct snd_pcm_ops snd_cs46xx_playback_ops = {
1533        .open =                 snd_cs46xx_playback_open,
1534        .close =                snd_cs46xx_playback_close,
1535        .ioctl =                snd_pcm_lib_ioctl,
1536        .hw_params =            snd_cs46xx_playback_hw_params,
1537        .hw_free =              snd_cs46xx_playback_hw_free,
1538        .prepare =              snd_cs46xx_playback_prepare,
1539        .trigger =              snd_cs46xx_playback_trigger,
1540        .pointer =              snd_cs46xx_playback_direct_pointer,
1541};
1542
1543static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
1544        .open =                 snd_cs46xx_playback_open,
1545        .close =                snd_cs46xx_playback_close,
1546        .ioctl =                snd_pcm_lib_ioctl,
1547        .hw_params =            snd_cs46xx_playback_hw_params,
1548        .hw_free =              snd_cs46xx_playback_hw_free,
1549        .prepare =              snd_cs46xx_playback_prepare,
1550        .trigger =              snd_cs46xx_playback_trigger,
1551        .pointer =              snd_cs46xx_playback_indirect_pointer,
1552        .ack =                  snd_cs46xx_playback_transfer,
1553};
1554
1555static struct snd_pcm_ops snd_cs46xx_capture_ops = {
1556        .open =                 snd_cs46xx_capture_open,
1557        .close =                snd_cs46xx_capture_close,
1558        .ioctl =                snd_pcm_lib_ioctl,
1559        .hw_params =            snd_cs46xx_capture_hw_params,
1560        .hw_free =              snd_cs46xx_capture_hw_free,
1561        .prepare =              snd_cs46xx_capture_prepare,
1562        .trigger =              snd_cs46xx_capture_trigger,
1563        .pointer =              snd_cs46xx_capture_direct_pointer,
1564};
1565
1566static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
1567        .open =                 snd_cs46xx_capture_open,
1568        .close =                snd_cs46xx_capture_close,
1569        .ioctl =                snd_pcm_lib_ioctl,
1570        .hw_params =            snd_cs46xx_capture_hw_params,
1571        .hw_free =              snd_cs46xx_capture_hw_free,
1572        .prepare =              snd_cs46xx_capture_prepare,
1573        .trigger =              snd_cs46xx_capture_trigger,
1574        .pointer =              snd_cs46xx_capture_indirect_pointer,
1575        .ack =                  snd_cs46xx_capture_transfer,
1576};
1577
1578#ifdef CONFIG_SND_CS46XX_NEW_DSP
1579#define MAX_PLAYBACK_CHANNELS   (DSP_MAX_PCM_CHANNELS - 1)
1580#else
1581#define MAX_PLAYBACK_CHANNELS   1
1582#endif
1583
1584int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
1585{
1586        struct snd_pcm *pcm;
1587        int err;
1588
1589        if (rpcm)
1590                *rpcm = NULL;
1591        if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0)
1592                return err;
1593
1594        pcm->private_data = chip;
1595
1596        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops);
1597        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops);
1598
1599        /* global setup */
1600        pcm->info_flags = 0;
1601        strcpy(pcm->name, "CS46xx");
1602        chip->pcm = pcm;
1603
1604        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1605                                              snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1606
1607        if (rpcm)
1608                *rpcm = pcm;
1609
1610        return 0;
1611}
1612
1613
1614#ifdef CONFIG_SND_CS46XX_NEW_DSP
1615int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
1616{
1617        struct snd_pcm *pcm;
1618        int err;
1619
1620        if (rpcm)
1621                *rpcm = NULL;
1622
1623        if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
1624                return err;
1625
1626        pcm->private_data = chip;
1627
1628        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
1629
1630        /* global setup */
1631        pcm->info_flags = 0;
1632        strcpy(pcm->name, "CS46xx - Rear");
1633        chip->pcm_rear = pcm;
1634
1635        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1636                                              snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1637
1638        if (rpcm)
1639                *rpcm = pcm;
1640
1641        return 0;
1642}
1643
1644int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
1645{
1646        struct snd_pcm *pcm;
1647        int err;
1648
1649        if (rpcm)
1650                *rpcm = NULL;
1651
1652        if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
1653                return err;
1654
1655        pcm->private_data = chip;
1656
1657        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops);
1658
1659        /* global setup */
1660        pcm->info_flags = 0;
1661        strcpy(pcm->name, "CS46xx - Center LFE");
1662        chip->pcm_center_lfe = pcm;
1663
1664        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1665                                              snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1666
1667        if (rpcm)
1668                *rpcm = pcm;
1669
1670        return 0;
1671}
1672
1673int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
1674{
1675        struct snd_pcm *pcm;
1676        int err;
1677
1678        if (rpcm)
1679                *rpcm = NULL;
1680
1681        if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0)
1682                return err;
1683
1684        pcm->private_data = chip;
1685
1686        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
1687
1688        /* global setup */
1689        pcm->info_flags = 0;
1690        strcpy(pcm->name, "CS46xx - IEC958");
1691        chip->pcm_rear = pcm;
1692
1693        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1694                                              snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1695
1696        if (rpcm)
1697                *rpcm = pcm;
1698
1699        return 0;
1700}
1701#endif
1702
1703/*
1704 *  Mixer routines
1705 */
1706static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
1707{
1708        struct snd_cs46xx *chip = bus->private_data;
1709
1710        chip->ac97_bus = NULL;
1711}
1712
1713static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
1714{
1715        struct snd_cs46xx *chip = ac97->private_data;
1716
1717        snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
1718                    (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
1719                    return);
1720
1721        if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {
1722                chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
1723                chip->eapd_switch = NULL;
1724        }
1725        else
1726                chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
1727}
1728
1729static int snd_cs46xx_vol_info(struct snd_kcontrol *kcontrol, 
1730                               struct snd_ctl_elem_info *uinfo)
1731{
1732        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1733        uinfo->count = 2;
1734        uinfo->value.integer.min = 0;
1735        uinfo->value.integer.max = 0x7fff;
1736        return 0;
1737}
1738
1739static int snd_cs46xx_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1740{
1741        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1742        int reg = kcontrol->private_value;
1743        unsigned int val = snd_cs46xx_peek(chip, reg);
1744        ucontrol->value.integer.value[0] = 0xffff - (val >> 16);
1745        ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);
1746        return 0;
1747}
1748
1749static int snd_cs46xx_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1750{
1751        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1752        int reg = kcontrol->private_value;
1753        unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 
1754                            (0xffff - ucontrol->value.integer.value[1]));
1755        unsigned int old = snd_cs46xx_peek(chip, reg);
1756        int change = (old != val);
1757
1758        if (change) {
1759                snd_cs46xx_poke(chip, reg, val);
1760        }
1761
1762        return change;
1763}
1764
1765#ifdef CONFIG_SND_CS46XX_NEW_DSP
1766
1767static int snd_cs46xx_vol_dac_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1768{
1769        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1770
1771        ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;
1772        ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;
1773
1774        return 0;
1775}
1776
1777static int snd_cs46xx_vol_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1778{
1779        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1780        int change = 0;
1781
1782        if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
1783            chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {
1784                cs46xx_dsp_set_dac_volume(chip,
1785                                          ucontrol->value.integer.value[0],
1786                                          ucontrol->value.integer.value[1]);
1787                change = 1;
1788        }
1789
1790        return change;
1791}
1792
1793#if 0
1794static int snd_cs46xx_vol_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1795{
1796        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1797
1798        ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;
1799        ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;
1800        return 0;
1801}
1802
1803static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1804{
1805        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1806        int change = 0;
1807
1808        if (chip->dsp_spos_instance->spdif_input_volume_left  != ucontrol->value.integer.value[0] ||
1809            chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {
1810                cs46xx_dsp_set_iec958_volume (chip,
1811                                              ucontrol->value.integer.value[0],
1812                                              ucontrol->value.integer.value[1]);
1813                change = 1;
1814        }
1815
1816        return change;
1817}
1818#endif
1819
1820#define snd_mixer_boolean_info          snd_ctl_boolean_mono_info
1821
1822static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, 
1823                                 struct snd_ctl_elem_value *ucontrol)
1824{
1825        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1826        int reg = kcontrol->private_value;
1827
1828        if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
1829                ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
1830        else
1831                ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;
1832
1833        return 0;
1834}
1835
1836static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, 
1837                                  struct snd_ctl_elem_value *ucontrol)
1838{
1839        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1840        int change, res;
1841
1842        switch (kcontrol->private_value) {
1843        case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
1844                mutex_lock(&chip->spos_mutex);
1845                change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
1846                if (ucontrol->value.integer.value[0] && !change) 
1847                        cs46xx_dsp_enable_spdif_out(chip);
1848                else if (change && !ucontrol->value.integer.value[0])
1849                        cs46xx_dsp_disable_spdif_out(chip);
1850
1851                res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));
1852                mutex_unlock(&chip->spos_mutex);
1853                break;
1854        case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
1855                change = chip->dsp_spos_instance->spdif_status_in;
1856                if (ucontrol->value.integer.value[0] && !change) {
1857                        cs46xx_dsp_enable_spdif_in(chip);
1858                        /* restore volume */
1859                }
1860                else if (change && !ucontrol->value.integer.value[0])
1861                        cs46xx_dsp_disable_spdif_in(chip);
1862                
1863                res = (change != chip->dsp_spos_instance->spdif_status_in);
1864                break;
1865        default:
1866                res = -EINVAL;
1867                snd_assert(0, (void)0);
1868        }
1869
1870        return res;
1871}
1872
1873static int snd_cs46xx_adc_capture_get(struct snd_kcontrol *kcontrol, 
1874                                      struct snd_ctl_elem_value *ucontrol)
1875{
1876        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1877        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1878
1879        if (ins->adc_input != NULL) 
1880                ucontrol->value.integer.value[0] = 1;
1881        else 
1882                ucontrol->value.integer.value[0] = 0;
1883        
1884        return 0;
1885}
1886
1887static int snd_cs46xx_adc_capture_put(struct snd_kcontrol *kcontrol, 
1888                                      struct snd_ctl_elem_value *ucontrol)
1889{
1890        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1891        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1892        int change = 0;
1893
1894        if (ucontrol->value.integer.value[0] && !ins->adc_input) {
1895                cs46xx_dsp_enable_adc_capture(chip);
1896                change = 1;
1897        } else  if (!ucontrol->value.integer.value[0] && ins->adc_input) {
1898                cs46xx_dsp_disable_adc_capture(chip);
1899                change = 1;
1900        }
1901        return change;
1902}
1903
1904static int snd_cs46xx_pcm_capture_get(struct snd_kcontrol *kcontrol, 
1905                                      struct snd_ctl_elem_value *ucontrol)
1906{
1907        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1908        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1909
1910        if (ins->pcm_input != NULL) 
1911                ucontrol->value.integer.value[0] = 1;
1912        else 
1913                ucontrol->value.integer.value[0] = 0;
1914
1915        return 0;
1916}
1917
1918
1919static int snd_cs46xx_pcm_capture_put(struct snd_kcontrol *kcontrol, 
1920                                      struct snd_ctl_elem_value *ucontrol)
1921{
1922        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1923        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1924        int change = 0;
1925
1926        if (ucontrol->value.integer.value[0] && !ins->pcm_input) {
1927                cs46xx_dsp_enable_pcm_capture(chip);
1928                change = 1;
1929        } else  if (!ucontrol->value.integer.value[0] && ins->pcm_input) {
1930                cs46xx_dsp_disable_pcm_capture(chip);
1931                change = 1;
1932        }
1933
1934        return change;
1935}
1936
1937static int snd_herc_spdif_select_get(struct snd_kcontrol *kcontrol, 
1938                                     struct snd_ctl_elem_value *ucontrol)
1939{
1940        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1941
1942        int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
1943
1944        if (val1 & EGPIODR_GPOE0)
1945                ucontrol->value.integer.value[0] = 1;
1946        else
1947                ucontrol->value.integer.value[0] = 0;
1948
1949        return 0;
1950}
1951
1952/*
1953 *      Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial.
1954 */ 
1955static int snd_herc_spdif_select_put(struct snd_kcontrol *kcontrol, 
1956                                       struct snd_ctl_elem_value *ucontrol)
1957{
1958        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1959        int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
1960        int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
1961
1962        if (ucontrol->value.integer.value[0]) {
1963                /* optical is default */
1964                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 
1965                                   EGPIODR_GPOE0 | val1);  /* enable EGPIO0 output */
1966                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 
1967                                   EGPIOPTR_GPPT0 | val2); /* open-drain on output */
1968        } else {
1969                /* coaxial */
1970                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE0); /* disable */
1971                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */
1972        }
1973
1974        /* checking diff from the EGPIO direction register 
1975           should be enough */
1976        return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));
1977}
1978
1979
1980static int snd_cs46xx_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1981{
1982        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1983        uinfo->count = 1;
1984        return 0;
1985}
1986
1987static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol,
1988                                        struct snd_ctl_elem_value *ucontrol)
1989{
1990        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
1991        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1992
1993        mutex_lock(&chip->spos_mutex);
1994        ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
1995        ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);
1996        ucontrol->value.iec958.status[2] = 0;
1997        ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);
1998        mutex_unlock(&chip->spos_mutex);
1999
2000        return 0;
2001}
2002
2003static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol,
2004                                        struct snd_ctl_elem_value *ucontrol)
2005{
2006        struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
2007        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
2008        unsigned int val;
2009        int change;
2010
2011        mutex_lock(&chip->spos_mutex);
2012        val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
2013                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |
2014                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3]))  |
2015                /* left and right validity bit */
2016                (1 << 13) | (1 << 12);
2017
2018
2019        change = (unsigned int)ins->spdif_csuv_default != val;
2020        ins->spdif_csuv_default = val;
2021
2022        if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )
2023                cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
2024
2025        mutex_unlock(&chip->spos_mutex);
2026
2027        return change;
2028}
2029
2030static int snd_cs46xx_spdif_mask_get(struct snd_kcontrol *kcontrol,
2031                                     struct snd_ctl_elem_value *ucontrol)
2032{
2033        ucontrol->value.iec958.status[0] = 0xff;
2034        ucontrol->value.iec958.status[1] = 0xff;
2035        ucontrol->value.iec958.status[2] = 0x00;
2036        ucontrol->value.iec958.status[3] = 0xff;
2037        return 0;
2038}
2039
2040static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol,
2041                                         struct snd_ctl_elem_value *ucontrol)
2042{
2043        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
2044        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
2045
2046        mutex_lock(&chip->spos_mutex);
2047        ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);
2048        ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);
2049        ucontrol->value.iec958.status[2] = 0;
2050        ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);
2051        mutex_unlock(&chip->spos_mutex);
2052
2053        return 0;
2054}
2055
2056static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
2057                                        struct snd_ctl_elem_value *ucontrol)
2058{
2059        struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
2060        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
2061        unsigned int val;
2062        int change;
2063
2064        mutex_lock(&chip->spos_mutex);
2065        val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
2066                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |
2067                ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
2068                /* left and right validity bit */
2069                (1 << 13) | (1 << 12);
2070
2071
2072        change = ins->spdif_csuv_stream != val;
2073        ins->spdif_csuv_stream = val;
2074
2075        if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )
2076                cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
2077
2078        mutex_unlock(&chip->spos_mutex);
2079
2080        return change;
2081}
2082
2083#endif /* CONFIG_SND_CS46XX_NEW_DSP */
2084
2085
2086static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = {
2087{
2088        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2089        .name = "DAC Volume",
2090        .info = snd_cs46xx_vol_info,
2091#ifndef CONFIG_SND_CS46XX_NEW_DSP
2092        .get = snd_cs46xx_vol_get,
2093        .put = snd_cs46xx_vol_put,
2094        .private_value = BA1_PVOL,
2095#else
2096        .get = snd_cs46xx_vol_dac_get,
2097        .put = snd_cs46xx_vol_dac_put,
2098#endif
2099},
2100
2101{
2102        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2103        .name = "ADC Volume",
2104        .info = snd_cs46xx_vol_info,
2105        .get = snd_cs46xx_vol_get,
2106        .put = snd_cs46xx_vol_put,
2107#ifndef CONFIG_SND_CS46XX_NEW_DSP
2108        .private_value = BA1_CVOL,
2109#else
2110        .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2,
2111#endif
2112},
2113#ifdef CONFIG_SND_CS46XX_NEW_DSP
2114{
2115        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2116        .name = "ADC Capture Switch",
2117        .info = snd_mixer_boolean_info,
2118        .get = snd_cs46xx_adc_capture_get,
2119        .put = snd_cs46xx_adc_capture_put
2120},
2121{
2122        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2123        .name = "DAC Capture Switch",
2124        .info = snd_mixer_boolean_info,
2125        .get = snd_cs46xx_pcm_capture_get,
2126        .put = snd_cs46xx_pcm_capture_put
2127},
2128{
2129        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2130        .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
2131        .info = snd_mixer_boolean_info,
2132        .get = snd_cs46xx_iec958_get,
2133        .put = snd_cs46xx_iec958_put,
2134        .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,
2135},
2136{
2137        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2138        .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,SWITCH),
2139        .info = snd_mixer_boolean_info,
2140        .get = snd_cs46xx_iec958_get,
2141        .put = snd_cs46xx_iec958_put,
2142        .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT,
2143},
2144#if 0
2145/* Input IEC958 volume does not work for the moment. (Benny) */
2146{
2147        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2148        .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,VOLUME),
2149        .info = snd_cs46xx_vol_info,
2150        .get = snd_cs46xx_vol_iec958_get,
2151        .put = snd_cs46xx_vol_iec958_put,
2152        .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2,
2153},
2154#endif
2155{
2156        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2157        .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2158        .info =  snd_cs46xx_spdif_info,
2159        .get =   snd_cs46xx_spdif_default_get,
2160        .put =   snd_cs46xx_spdif_default_put,
2161},
2162{
2163        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2164        .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
2165        .info =  snd_cs46xx_spdif_info,
2166        .get =   snd_cs46xx_spdif_mask_get,
2167        .access = SNDRV_CTL_ELEM_ACCESS_READ
2168},
2169{
2170        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2171        .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2172        .info =  snd_cs46xx_spdif_info,
2173        .get =   snd_cs46xx_spdif_stream_get,
2174        .put =   snd_cs46xx_spdif_stream_put
2175},
2176
2177#endif
2178};
2179
2180#ifdef CONFIG_SND_CS46XX_NEW_DSP
2181/* set primary cs4294 codec into Extended Audio Mode */
2182static int snd_cs46xx_front_dup_get(struct snd_kcontrol *kcontrol, 
2183                                    struct snd_ctl_elem_value *ucontrol)
2184{
2185        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
2186        unsigned short val;
2187        val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE);
2188        ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1;
2189        return 0;
2190}
2191
2192static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol, 
2193                                    struct snd_ctl_elem_value *ucontrol)
2194{
2195        struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
2196        return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
2197                                    AC97_CSR_ACMODE, 0x200,
2198                                    ucontrol->value.integer.value[0] ? 0 : 0x200);
2199}
2200
2201static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
2202        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2203        .name = "Duplicate Front",
2204        .info = snd_mixer_boolean_info,
2205        .get = snd_cs46xx_front_dup_get,
2206        .put = snd_cs46xx_front_dup_put,
2207};
2208#endif
2209
2210#ifdef CONFIG_SND_CS46XX_NEW_DSP
2211/* Only available on the Hercules Game Theater XP soundcard */
2212static struct snd_kcontrol_new snd_hercules_controls[] = {
2213{
2214        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2215        .name = "Optical/Coaxial SPDIF Input Switch",
2216        .info = snd_mixer_boolean_info,
2217        .get = snd_herc_spdif_select_get,
2218        .put = snd_herc_spdif_select_put,
2219},
2220};
2221
2222
2223static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
2224{
2225        unsigned long end_time;
2226        int err;
2227
2228        /* reset to defaults */
2229        snd_ac97_write(ac97, AC97_RESET, 0);    
2230
2231        /* set the desired CODEC mode */
2232        if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
2233                snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0);
2234                snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0);
2235        } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
2236                snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3);
2237                snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
2238        } else {
2239                snd_assert(0); /* should never happen ... */
2240        }
2241
2242        udelay(50);
2243
2244        /* it's necessary to wait awhile until registers are accessible after RESET */
2245        /* because the PCM or MASTER volume registers can be modified, */
2246        /* the REC_GAIN register is used for tests */
2247        end_time = jiffies + HZ;
2248        do {
2249                unsigned short ext_mid;
2250    
2251                /* use preliminary reads to settle the communication */
2252                snd_ac97_read(ac97, AC97_RESET);
2253                snd_ac97_read(ac97, AC97_VENDOR_ID1);
2254                snd_ac97_read(ac97, AC97_VENDOR_ID2);
2255                /* modem? */
2256                ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
2257                if (ext_mid != 0xffff && (ext_mid & 1) != 0)
2258                        return;
2259
2260                /* test if we can write to the record gain volume register */
2261                snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
2262                if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
2263                        return;
2264
2265                msleep(10);
2266        } while (time_after_eq(end_time, jiffies));
2267
2268        snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n");  
2269}
2270#endif
2271
2272static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
2273{
2274        int idx, err;
2275        struct snd_ac97_template ac97;
2276
2277        memset(&ac97, 0, sizeof(ac97));
2278        ac97.private_data = chip;
2279        ac97.private_free = snd_cs46xx_mixer_free_ac97;
2280        ac97.num = codec;
2281        if (chip->amplifier_ctrl == amp_voyetra)
2282                ac97.scaps = AC97_SCAP_INV_EAPD;
2283
2284        if (codec == CS46XX_SECONDARY_CODEC_INDEX) {
2285                snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec);
2286                udelay(10);
2287                if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
2288                        snd_printdd("snd_cs46xx: seconadry codec not present\n");
2289                        return -ENXIO;
2290                }
2291        }
2292
2293        snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
2294        for (idx = 0; idx < 100; ++idx) {
2295                if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
2296                        err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
2297                        return err;
2298                }
2299                msleep(10);
2300        }
2301        snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
2302        return -ENXIO;
2303}
2304
2305int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
2306{
2307        struct snd_card *card = chip->card;
2308        struct snd_ctl_elem_id id;
2309        int err;
2310        unsigned int idx;
2311        static struct snd_ac97_bus_ops ops = {
2312#ifdef CONFIG_SND_CS46XX_NEW_DSP
2313                .reset = snd_cs46xx_codec_reset,
2314#endif
2315                .write = snd_cs46xx_ac97_write,
2316                .read = snd_cs46xx_ac97_read,
2317        };
2318
2319        /* detect primary codec */
2320        chip->nr_ac97_codecs = 0;
2321        snd_printdd("snd_cs46xx: detecting primary codec\n");
2322        if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
2323                return err;
2324        chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
2325
2326        if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
2327                return -ENXIO;
2328        chip->nr_ac97_codecs = 1;
2329
2330#ifdef CONFIG_SND_CS46XX_NEW_DSP
2331        snd_printdd("snd_cs46xx: detecting seconadry codec\n");
2332        /* try detect a secondary codec */
2333        if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
2334                chip->nr_ac97_codecs = 2;
2335#endif /* CONFIG_SND_CS46XX_NEW_DSP */
2336
2337        /* add cs4630 mixer controls */
2338        for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
2339                struct snd_kcontrol *kctl;
2340                kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);
2341                if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM)
2342                        kctl->id.device = spdif_device;
2343                if ((err = snd_ctl_add(card, kctl)) < 0)
2344                        return err;
2345        }
2346
2347        /* get EAPD mixer switch (for voyetra hack) */
2348        memset(&id, 0, sizeof(id));
2349        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2350        strcpy(id.name, "External Amplifier");
2351        chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
2352    
2353#ifdef CONFIG_SND_CS46XX_NEW_DSP
2354        if (chip->nr_ac97_codecs == 1) {
2355                unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff;
2356                if (id2 == 0x592b || id2 == 0x592d) {
2357                        err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip));
2358                        if (err < 0)
2359                                return err;
2360                        snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
2361                                             AC97_CSR_ACMODE, 0x200);
2362                }
2363        }
2364        /* do soundcard specific mixer setup */
2365        if (chip->mixer_init) {
2366                snd_printdd ("calling chip->mixer_init(chip);\n");
2367                chip->mixer_init(chip);
2368        }
2369#endif
2370
2371        /* turn on amplifier */
2372        chip->amplifier_ctrl(chip, 1);
2373    
2374        return 0;
2375}
2376
2377/*
2378 *  RawMIDI interface
2379 */
2380
2381static void snd_cs46xx_midi_reset(struct snd_cs46xx *chip)
2382{
2383        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);
2384        udelay(100);
2385        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2386}
2387
2388static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream)
2389{
2390        struct snd_cs46xx *chip = substream->rmidi->private_data;
2391
2392        chip->active_ctrl(chip, 1);
2393        spin_lock_irq(&chip->reg_lock);
2394        chip->uartm |= CS46XX_MODE_INPUT;
2395        chip->midcr |= MIDCR_RXE;
2396        chip->midi_input = substream;
2397        if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
2398                snd_cs46xx_midi_reset(chip);
2399        } else {
2400                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2401        }
2402        spin_unlock_irq(&chip->reg_lock);
2403        return 0;
2404}
2405
2406static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream)
2407{
2408        struct snd_cs46xx *chip = substream->rmidi->private_data;
2409
2410        spin_lock_irq(&chip->reg_lock);
2411        chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
2412        chip->midi_input = NULL;
2413        if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
2414                snd_cs46xx_midi_reset(chip);
2415        } else {
2416                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2417        }
2418        chip->uartm &= ~CS46XX_MODE_INPUT;
2419        spin_unlock_irq(&chip->reg_lock);
2420        chip->active_ctrl(chip, -1);
2421        return 0;
2422}
2423
2424static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream)
2425{
2426        struct snd_cs46xx *chip = substream->rmidi->private_data;
2427
2428        chip->active_ctrl(chip, 1);
2429
2430        spin_lock_irq(&chip->reg_lock);
2431        chip->uartm |= CS46XX_MODE_OUTPUT;
2432        chip->midcr |= MIDCR_TXE;
2433        chip->midi_output = substream;
2434        if (!(chip->uartm & CS46XX_MODE_INPUT)) {
2435                snd_cs46xx_midi_reset(chip);
2436        } else {
2437                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2438        }
2439        spin_unlock_irq(&chip->reg_lock);
2440        return 0;
2441}
2442
2443static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream)
2444{
2445        struct snd_cs46xx *chip = substream->rmidi->private_data;
2446
2447        spin_lock_irq(&chip->reg_lock);
2448        chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
2449        chip->midi_output = NULL;
2450        if (!(chip->uartm & CS46XX_MODE_INPUT)) {
2451                snd_cs46xx_midi_reset(chip);
2452        } else {
2453                snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2454        }
2455        chip->uartm &= ~CS46XX_MODE_OUTPUT;
2456        spin_unlock_irq(&chip->reg_lock);
2457        chip->active_ctrl(chip, -1);
2458        return 0;
2459}
2460
2461static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
2462{
2463        unsigned long flags;
2464        struct snd_cs46xx *chip = substream->rmidi->private_data;
2465
2466        spin_lock_irqsave(&chip->reg_lock, flags);
2467        if (up) {
2468                if ((chip->midcr & MIDCR_RIE) == 0) {
2469                        chip->midcr |= MIDCR_RIE;
2470                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2471                }
2472        } else {
2473                if (chip->midcr & MIDCR_RIE) {
2474                        chip->midcr &= ~MIDCR_RIE;
2475                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2476                }
2477        }
2478        spin_unlock_irqrestore(&chip->reg_lock, flags);
2479}
2480
2481static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
2482{
2483        unsigned long flags;
2484        struct snd_cs46xx *chip = substream->rmidi->private_data;
2485        unsigned char byte;
2486
2487        spin_lock_irqsave(&chip->reg_lock, flags);
2488        if (up) {
2489                if ((chip->midcr & MIDCR_TIE) == 0) {
2490                        chip->midcr |= MIDCR_TIE;
2491                        /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */
2492                        while ((chip->midcr & MIDCR_TIE) &&
2493                               (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
2494                                if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
2495                                        chip->midcr &= ~MIDCR_TIE;
2496                                } else {
2497                                        snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte);
2498                                }
2499                        }
2500                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2501                }
2502        } else {
2503                if (chip->midcr & MIDCR_TIE) {
2504                        chip->midcr &= ~MIDCR_TIE;
2505                        snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2506                }
2507        }
2508        spin_unlock_irqrestore(&chip->reg_lock, flags);
2509}
2510
2511static struct snd_rawmidi_ops snd_cs46xx_midi_output =
2512{
2513        .open =         snd_cs46xx_midi_output_open,
2514        .close =        snd_cs46xx_midi_output_close,
2515        .trigger =      snd_cs46xx_midi_output_trigger,
2516};
2517
2518static struct snd_rawmidi_ops snd_cs46xx_midi_input =
2519{
2520        .open =         snd_cs46xx_midi_input_open,
2521        .close =        snd_cs46xx_midi_input_close,
2522        .trigger =      snd_cs46xx_midi_input_trigger,
2523};
2524
2525int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
2526{
2527        struct snd_rawmidi *rmidi;
2528        int err;
2529
2530        if (rrawmidi)
2531                *rrawmidi = NULL;
2532        if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)
2533                return err;
2534        strcpy(rmidi->name, "CS46XX");
2535        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);
2536        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);
2537        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
2538        rmidi->private_data = chip;
2539        chip->rmidi = rmidi;
2540        if (rrawmidi)
2541                *rrawmidi = NULL;
2542        return 0;
2543}
2544
2545
2546/*
2547 * gameport interface
2548 */
2549
2550#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
2551
2552static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
2553{
2554        struct snd_cs46xx *chip = gameport_get_port_data(gameport);
2555
2556        snd_assert(chip, return);
2557        snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
2558}
2559
2560static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
2561{
2562        struct snd_cs46xx *chip = gameport_get_port_data(gameport);
2563
2564        snd_assert(chip, return 0);
2565        return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
2566}
2567
2568static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
2569{
2570        struct snd_cs46xx *chip = gameport_get_port_data(gameport);
2571        unsigned js1, js2, jst;
2572
2573        snd_assert(chip, return 0);
2574
2575        js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
2576        js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
2577        jst = snd_cs46xx_peekBA0(chip, BA0_JSPT);
2578        
2579        *buttons = (~jst >> 4) & 0x0F; 
2580        
2581        axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
2582        axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
2583        axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
2584        axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
2585
2586        for(jst=0;jst<4;++jst)
2587                if(axes[jst]==0xFFFF) axes[jst] = -1;
2588        return 0;
2589}
2590
2591static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
2592{
2593        switch (mode) {
2594        case GAMEPORT_MODE_COOKED:
2595                return 0;
2596        case GAMEPORT_MODE_RAW:
2597                return 0;
2598        default:
2599                return -1;
2600        }
2601        return 0;
2602}
2603
2604int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip)
2605{
2606        struct gameport *gp;
2607
2608        chip->gameport = gp = gameport_allocate_port();
2609        if (!gp) {
2610                printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n");
2611                return -ENOMEM;
2612        }
2613
2614        gameport_set_name(gp, "CS46xx Gameport");
2615        gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
2616        gameport_set_dev_parent(gp, &chip->pci->dev);
2617        gameport_set_port_data(gp, chip);
2618
2619        gp->open = snd_cs46xx_gameport_open;
2620        gp->read = snd_cs46xx_gameport_read;
2621        gp->trigger = snd_cs46xx_gameport_trigger;
2622        gp->cooked_read = snd_cs46xx_gameport_cooked_read;
2623
2624        snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
2625        snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
2626
2627        gameport_register_port(gp);
2628
2629        return 0;
2630}
2631
2632static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
2633{
2634        if (chip->gameport) {
2635                gameport_unregister_port(chip->gameport);
2636                chip->gameport = NULL;
2637        }
2638}
2639#else
2640int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
2641static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
2642#endif /* CONFIG_GAMEPORT */
2643
2644#ifdef CONFIG_PROC_FS
2645/*
2646 *  proc interface
2647 */
2648
2649static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data,
2650                               struct file *file, char __user *buf,
2651                               unsigned long count, unsigned long pos)
2652{
2653        long size;
2654        struct snd_cs46xx_region *region = entry->private_data;
2655        
2656        size = count;
2657        if (pos + (size_t)size > region->size)
2658                size = region->size - pos;
2659        if (size > 0) {
2660                if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
2661                        return -EFAULT;
2662        }
2663        return size;
2664}
2665
2666static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
2667        .read = snd_cs46xx_io_read,
2668};
2669
2670static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
2671{
2672        struct snd_info_entry *entry;
2673        int idx;
2674        
2675        for (idx = 0; idx < 5; idx++) {
2676                struct snd_cs46xx_region *region = &chip->region.idx[idx];
2677                if (! snd_card_proc_new(card, region->name, &entry)) {
2678                        entry->content = SNDRV_INFO_CONTENT_DATA;
2679                        entry->private_data = chip;
2680                        entry->c.ops = &snd_cs46xx_proc_io_ops;
2681                        entry->size = region->size;
2682                        entry->mode = S_IFREG | S_IRUSR;
2683                }
2684        }
2685#ifdef CONFIG_SND_CS46XX_NEW_DSP
2686        cs46xx_dsp_proc_init(card, chip);
2687#endif
2688        return 0;
2689}
2690
2691static int snd_cs46xx_proc_done(struct snd_cs46xx *chip)
2692{
2693#ifdef CONFIG_SND_CS46XX_NEW_DSP
2694        cs46xx_dsp_proc_done(chip);
2695#endif
2696        return 0;
2697}
2698#else /* !CONFIG_PROC_FS */
2699#define snd_cs46xx_proc_init(card, chip)
2700#define snd_cs46xx_proc_done(chip)
2701#endif
2702
2703/*
2704 * stop the h/w
2705 */
2706static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
2707{
2708        unsigned int tmp;
2709
2710        tmp = snd_cs46xx_peek(chip, BA1_PFIE);
2711        tmp &= ~0x0000f03f;
2712        tmp |=  0x00000010;
2713        snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt disable */
2714
2715        tmp = snd_cs46xx_peek(chip, BA1_CIE);
2716        tmp &= ~0x0000003f;
2717        tmp |=  0x00000011;
2718        snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt disable */
2719
2720        /*
2721         *  Stop playback DMA.
2722         */
2723        tmp = snd_cs46xx_peek(chip, BA1_PCTL);
2724        snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
2725
2726        /*
2727         *  Stop capture DMA.
2728         */
2729        tmp = snd_cs46xx_peek(chip, BA1_CCTL);
2730        snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
2731
2732        /*
2733         *  Reset the processor.
2734         */
2735        snd_cs46xx_reset(chip);
2736
2737        snd_cs46xx_proc_stop(chip);
2738
2739        /*
2740         *  Power down the PLL.
2741         */
2742        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
2743
2744        /*
2745         *  Turn off the Processor by turning off the software clock enable flag in 
2746         *  the clock control register.
2747         */
2748        tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE;
2749        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
2750}
2751
2752
2753static int snd_cs46xx_free(struct snd_cs46xx *chip)
2754{
2755        int idx;
2756
2757        snd_assert(chip != NULL, return -EINVAL);
2758
2759        if (chip->active_ctrl)
2760                chip->active_ctrl(chip, 1);
2761
2762        snd_cs46xx_remove_gameport(chip);
2763
2764        if (chip->amplifier_ctrl)
2765                chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
2766        
2767        snd_cs46xx_proc_done(chip);
2768
2769        if (chip->region.idx[0].resource)
2770                snd_cs46xx_hw_stop(chip);
2771
2772        if (chip->irq >= 0)
2773                free_irq(chip->irq, chip);
2774
2775        if (chip->active_ctrl)
2776                chip->active_ctrl(chip, -chip->amplifier);
2777
2778        for (idx = 0; idx < 5; idx++) {
2779                struct snd_cs46xx_region *region = &chip->region.idx[idx];
2780                if (region->remap_addr)
2781                        iounmap(region->remap_addr);
2782                release_and_free_resource(region->resource);
2783        }
2784
2785#ifdef CONFIG_SND_CS46XX_NEW_DSP
2786        if (chip->dsp_spos_instance) {
2787                cs46xx_dsp_spos_destroy(chip);
2788                chip->dsp_spos_instance = NULL;
2789        }
2790#endif
2791        
2792#ifdef CONFIG_PM
2793        kfree(chip->saved_regs);
2794#endif
2795
2796        pci_disable_device(chip->pci);
2797        kfree(chip);
2798        return 0;
2799}
2800
2801static int snd_cs46xx_dev_free(struct snd_device *device)
2802{
2803        struct snd_cs46xx *chip = device->device_data;
2804        return snd_cs46xx_free(chip);
2805}
2806
2807/*
2808 *  initialize chip
2809 */
2810static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
2811{
2812        int timeout;
2813
2814        /* 
2815         *  First, blast the clock control register to zero so that the PLL starts
2816         *  out in a known state, and blast the master serial port control register
2817         *  to zero so that the serial ports also start out in a known state.
2818         */
2819        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
2820        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0);
2821
2822        /*
2823         *  If we are in AC97 mode, then we must set the part to a host controlled
2824         *  AC-link.  Otherwise, we won't be able to bring up the link.
2825         */        
2826#ifdef CONFIG_SND_CS46XX_NEW_DSP
2827        snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 | 
2828                           SERACC_TWO_CODECS);  /* 2.00 dual codecs */
2829        /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */
2830#else
2831        snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */
2832#endif
2833
2834        /*
2835         *  Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
2836         *  spec) and then drive it high.  This is done for non AC97 modes since
2837         *  there might be logic external to the CS461x that uses the ARST# line
2838         *  for a reset.
2839         */
2840        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0);
2841#ifdef CONFIG_SND_CS46XX_NEW_DSP
2842        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0);
2843#endif
2844        udelay(50);
2845        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN);
2846#ifdef CONFIG_SND_CS46XX_NEW_DSP
2847        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN);
2848#endif
2849    
2850        /*
2851         *  The first thing we do here is to enable sync generation.  As soon
2852         *  as we start receiving bit clock, we'll start producing the SYNC
2853         *  signal.
2854         */
2855        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
2856#ifdef CONFIG_SND_CS46XX_NEW_DSP
2857        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN);
2858#endif
2859
2860        /*
2861         *  Now wait for a short while to allow the AC97 part to start
2862         *  generating bit clock (so we don't try to start the PLL without an
2863         *  input clock).
2864         */
2865        mdelay(10);
2866
2867        /*
2868         *  Set the serial port timing configuration, so that
2869         *  the clock control circuit gets its clock from the correct place.
2870         */
2871        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97);
2872
2873        /*
2874         *  Write the selected clock control setup to the hardware.  Do not turn on
2875         *  SWCE yet (if requested), so that the devices clocked by the output of
2876         *  PLL are not clocked until the PLL is stable.
2877         */
2878        snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
2879        snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a);
2880        snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8);
2881
2882        /*
2883         *  Power up the PLL.
2884         */
2885        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP);
2886
2887        /*
2888         *  Wait until the PLL has stabilized.
2889         */
2890        msleep(100);
2891
2892        /*
2893         *  Turn on clocking of the core so that we can setup the serial ports.
2894         */
2895        snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE);
2896
2897        /*
2898         * Enable FIFO  Host Bypass
2899         */
2900        snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP);
2901
2902        /*
2903         *  Fill the serial port FIFOs with silence.
2904         */
2905        snd_cs46xx_clear_serial_FIFOs(chip);
2906
2907        /*
2908         *  Set the serial port FIFO pointer to the first sample in the FIFO.
2909         */
2910        /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */
2911
2912        /*
2913         *  Write the serial port configuration to the part.  The master
2914         *  enable bit is not set until all other values have been written.
2915         */
2916        snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
2917        snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
2918        snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
2919
2920
2921#ifdef CONFIG_SND_CS46XX_NEW_DSP
2922        snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
2923        snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
2924        snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0);
2925        snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0);
2926        snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1);
2927#endif
2928
2929        mdelay(5);
2930
2931
2932        /*
2933         * Wait for the codec ready signal from the AC97 codec.
2934         */
2935        timeout = 150;
2936        while (timeout-- > 0) {
2937                /*
2938                 *  Read the AC97 status register to see if we've seen a CODEC READY
2939                 *  signal from the AC97 codec.
2940                 */
2941                if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
2942                        goto ok1;
2943                msleep(10);
2944        }
2945
2946
2947        snd_printk(KERN_ERR "create - never read codec ready from AC'97\n");
2948        snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n");
2949        return -EIO;
2950 ok1:
2951#ifdef CONFIG_SND_CS46XX_NEW_DSP
2952        {
2953                int count;
2954                for (count = 0; count < 150; count++) {
2955                        /* First, we want to wait for a short time. */
2956                        udelay(25);
2957        
2958                        if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)
2959                                break;
2960                }
2961
2962                /*
2963                 *  Make sure CODEC is READY.
2964                 */
2965                if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY))
2966                        snd_printdd("cs46xx: never read card ready from secondary AC'97\n");
2967        }
2968#endif
2969
2970        /*
2971         *  Assert the vaid frame signal so that we can start sending commands
2972         *  to the AC97 codec.
2973         */
2974        snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
2975#ifdef CONFIG_SND_CS46XX_NEW_DSP
2976        snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
2977#endif
2978
2979
2980        /*
2981         *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
2982         *  the codec is pumping ADC data across the AC-link.
2983         */
2984        timeout = 150;
2985        while (timeout-- > 0) {
2986                /*
2987                 *  Read the input slot valid register and see if input slots 3 and
2988                 *  4 are valid yet.
2989                 */
2990                if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
2991                        goto ok2;
2992                msleep(10);
2993        }
2994
2995#ifndef CONFIG_SND_CS46XX_NEW_DSP
2996        snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n");
2997        return -EIO;
2998#else
2999        /* This may happen on a cold boot with a Terratec SiXPack 5.1.
3000           Reloading the driver may help, if there's other soundcards 
3001           with the same problem I would like to know. (Benny) */
3002
3003        snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n");
3004        snd_printk(KERN_ERR "       Try reloading the ALSA driver, if you find something\n");
3005        snd_printk(KERN_ERR "       broken or not working on your soundcard upon\n");
3006        snd_printk(KERN_ERR "       this message please report to alsa-devel@alsa-project.org\n");
3007
3008        return -EIO;
3009#endif
3010 ok2:
3011
3012        /*
3013         *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
3014         *  commense the transfer of digital audio data to the AC97 codec.
3015         */
3016
3017        snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
3018
3019
3020        /*
3021         *  Power down the DAC and ADC.  We will power them up (if) when we need
3022         *  them.
3023         */
3024        /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */
3025
3026        /*
3027         *  Turn off the Processor by turning off the software clock enable flag in 
3028         *  the clock control register.
3029         */
3030        /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
3031        /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
3032
3033        return 0;
3034}
3035
3036/*
3037 *  start and load DSP 
3038 */
3039
3040static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
3041{
3042        unsigned int tmp;
3043
3044        snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
3045        
3046        tmp = snd_cs46xx_peek(chip, BA1_PFIE);
3047        tmp &= ~0x0000f03f;
3048        snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt enable */
3049
3050        tmp = snd_cs46xx_peek(chip, BA1_CIE);
3051        tmp &= ~0x0000003f;
3052        tmp |=  0x00000001;
3053        snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt enable */
3054}
3055
3056int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
3057{       
3058        unsigned int tmp;
3059        /*
3060         *  Reset the processor.
3061         */
3062        snd_cs46xx_reset(chip);
3063        /*
3064         *  Download the image to the processor.
3065         */
3066#ifdef CONFIG_SND_CS46XX_NEW_DSP
3067#if 0
3068        if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
3069                snd_printk(KERN_ERR "image download error\n");
3070                return -EIO;
3071        }
3072#endif
3073
3074        if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
3075                snd_printk(KERN_ERR "image download error [cwc4630]\n");
3076                return -EIO;
3077        }
3078
3079        if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
3080                snd_printk(KERN_ERR "image download error [cwcasync]\n");
3081                return -EIO;
3082        }
3083
3084        if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
3085                snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
3086                return -EIO;
3087        }
3088
3089        if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
3090                snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
3091                return -EIO;
3092        }
3093
3094        if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
3095                snd_printk(KERN_ERR "image download error [cwcdma]\n");
3096                return -EIO;
3097        }
3098
3099        if (cs46xx_dsp_scb_and_task_init(chip) < 0)
3100                return -EIO;
3101#else
3102        /* old image */
3103        if (snd_cs46xx_download_image(chip) < 0) {
3104                snd_printk(KERN_ERR "image download error\n");
3105                return -EIO;
3106        }
3107
3108        /*
3109         *  Stop playback DMA.
3110         */
3111        tmp = snd_cs46xx_peek(chip, BA1_PCTL);
3112        chip->play_ctl = tmp & 0xffff0000;
3113        snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
3114#endif
3115
3116        /*
3117         *  Stop capture DMA.
3118         */
3119        tmp = snd_cs46xx_peek(chip, BA1_CCTL);
3120        chip->capt.ctl = tmp & 0x0000ffff;
3121        snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
3122
3123        mdelay(5);
3124
3125        snd_cs46xx_set_play_sample_rate(chip, 8000);
3126        snd_cs46xx_set_capture_sample_rate(chip, 8000);
3127
3128        snd_cs46xx_proc_start(chip);
3129
3130        cs46xx_enable_stream_irqs(chip);
3131        
3132#ifndef CONFIG_SND_CS46XX_NEW_DSP
3133        /* set the attenuation to 0dB */ 
3134        snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
3135        snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
3136#endif
3137
3138        return 0;
3139}
3140
3141
3142/*
3143 *      AMP control - null AMP
3144 */
3145 
3146static void amp_none(struct snd_cs46xx *chip, int change)
3147{       
3148}
3149
3150#ifdef CONFIG_SND_CS46XX_NEW_DSP
3151static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip)
3152{
3153        
3154        u32 idx, valid_slots,tmp,powerdown = 0;
3155        u16 modem_power,pin_config,logic_type;
3156
3157        snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
3158
3159        /*
3160         *  See if the devices are powered down.  If so, we must power them up first
3161         *  or they will not respond.
3162         */
3163        tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
3164
3165        if (!(tmp & CLKCR1_SWCE)) {
3166                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
3167                powerdown = 1;
3168        }
3169
3170        /*
3171         * Clear PRA.  The Bonzo chip will be used for GPIO not for modem
3172         * stuff.
3173         */
3174        if(chip->nr_ac97_codecs != 2) {
3175                snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n");
3176                return -EINVAL;
3177        }
3178
3179        modem_power = snd_cs46xx_codec_read (chip, 
3180                                             AC97_EXTENDED_MSTATUS,
3181                                             CS46XX_SECONDARY_CODEC_INDEX);
3182        modem_power &=0xFEFF;
3183
3184        snd_cs46xx_codec_write(chip, 
3185                               AC97_EXTENDED_MSTATUS, modem_power,
3186                               CS46XX_SECONDARY_CODEC_INDEX);
3187
3188        /*
3189         * Set GPIO pin's 7 and 8 so that they are configured for output.
3190         */
3191        pin_config = snd_cs46xx_codec_read (chip, 
3192                                            AC97_GPIO_CFG,
3193                                            CS46XX_SECONDARY_CODEC_INDEX);
3194        pin_config &=0x27F;
3195
3196        snd_cs46xx_codec_write(chip, 
3197                               AC97_GPIO_CFG, pin_config,
3198                               CS46XX_SECONDARY_CODEC_INDEX);
3199    
3200        /*
3201         * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
3202         */
3203
3204        logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,
3205                                           CS46XX_SECONDARY_CODEC_INDEX);
3206        logic_type &=0x27F; 
3207
3208        snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,
3209                                CS46XX_SECONDARY_CODEC_INDEX);
3210
3211        valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
3212        valid_slots |= 0x200;
3213        snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
3214
3215        if ( cs46xx_wait_for_fifo(chip,1) ) {
3216          snd_printdd("FIFO is busy\n");
3217          
3218          return -EINVAL;
3219        }
3220
3221        /*
3222         * Fill slots 12 with the correct value for the GPIO pins. 
3223         */
3224        for(idx = 0x90; idx <= 0x9F; idx++) {
3225                /*
3226                 * Initialize the fifo so that bits 7 and 8 are on.
3227                 *
3228                 * Remember that the GPIO pins in bonzo are shifted by 4 bits to
3229                 * the left.  0x1800 corresponds to bits 7 and 8.
3230                 */
3231                snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
3232
3233                /*
3234                 * Wait for command to complete
3235                 */
3236                if ( cs46xx_wait_for_fifo(chip,200) ) {
3237                        snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
3238
3239                        return -EINVAL;
3240                }
3241            
3242                /*
3243                 * Write the serial port FIFO index.
3244                 */
3245                snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
3246      
3247                /*
3248                 * Tell the serial port to load the new value into the FIFO location.
3249                 */
3250                snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
3251        }
3252
3253        /* wait for last command to complete */
3254        cs46xx_wait_for_fifo(chip,200);
3255
3256        /*
3257         *  Now, if we powered up the devices, then power them back down again.
3258         *  This is kinda ugly, but should never happen.
3259         */
3260        if (powerdown)
3261                snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
3262
3263        return 0;
3264}
3265#endif
3266
3267/*
3268 *      Crystal EAPD mode
3269 */
3270 
3271static void amp_voyetra(struct snd_cs46xx *chip, int change)
3272{
3273        /* Manage the EAPD bit on the Crystal 4297 
3274           and the Analog AD1885 */
3275           
3276#ifdef CONFIG_SND_CS46XX_NEW_DSP
3277        int old = chip->amplifier;
3278#endif
3279        int oval, val;
3280        
3281        chip->amplifier += change;
3282        oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN,
3283                                     CS46XX_PRIMARY_CODEC_INDEX);
3284        val = oval;
3285        if (chip->amplifier) {
3286                /* Turn the EAPD amp on */
3287                val |= 0x8000;
3288        } else {
3289                /* Turn the EAPD amp off */
3290                val &= ~0x8000;
3291        }
3292        if (val != oval) {
3293                snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val,
3294                                       CS46XX_PRIMARY_CODEC_INDEX);
3295                if (chip->eapd_switch)
3296                        snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
3297                                       &chip->eapd_switch->id);
3298        }
3299
3300#ifdef CONFIG_SND_CS46XX_NEW_DSP
3301        if (chip->amplifier && !old) {
3302                voyetra_setup_eapd_slot(chip);
3303        }
3304#endif
3305}
3306
3307static void hercules_init(struct snd_cs46xx *chip) 
3308{
3309        /* default: AMP off, and SPDIF input optical */
3310        snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
3311        snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
3312}
3313
3314
3315/*
3316 *      Game Theatre XP card - EGPIO[2] is used to enable the external amp.
3317 */ 
3318static void amp_hercules(struct snd_cs46xx *chip, int change)
3319{
3320        int old = chip->amplifier;
3321        int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
3322        int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
3323
3324        chip->amplifier += change;
3325        if (chip->amplifier && !old) {
3326                snd_printdd ("Hercules amplifier ON\n");
3327
3328                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 
3329                                   EGPIODR_GPOE2 | val1);     /* enable EGPIO2 output */
3330                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 
3331                                   EGPIOPTR_GPPT2 | val2);   /* open-drain on output */
3332        } else if (old && !chip->amplifier) {
3333                snd_printdd ("Hercules amplifier OFF\n");
3334                snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE2); /* disable */
3335                snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */
3336        }
3337}
3338
3339static void voyetra_mixer_init (struct snd_cs46xx *chip)
3340{
3341        snd_printdd ("initializing Voyetra mixer\n");
3342
3343        /* Enable SPDIF out */
3344        snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
3345        snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
3346}
3347
3348static void hercules_mixer_init (struct snd_cs46xx *chip)
3349{
3350#ifdef CONFIG_SND_CS46XX_NEW_DSP
3351        unsigned int idx;
3352        int err;
3353        struct snd_card *card = chip->card;
3354#endif
3355
3356        /* set EGPIO to default */
3357        hercules_init(chip);
3358
3359        snd_printdd ("initializing Hercules mixer\n");
3360
3361#ifdef CONFIG_SND_CS46XX_NEW_DSP
3362        if (chip->in_suspend)
3363                return;
3364
3365        for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {
3366                struct snd_kcontrol *kctl;
3367
3368                kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);
3369                if ((err = snd_ctl_add(card, kctl)) < 0) {
3370                        printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err);
3371                        break;
3372                }
3373        }
3374#endif
3375}
3376
3377
3378#if 0
3379/*
3380 *      Untested
3381 */
3382 
3383static void amp_voyetra_4294(struct snd_cs46xx *chip, int change)
3384{
3385        chip->amplifier += change;
3386
3387        if (chip->amplifier) {
3388                /* Switch the GPIO pins 7 and 8 to open drain */
3389                snd_cs46xx_codec_write(chip, 0x4C,
3390                                       snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F);
3391                snd_cs46xx_codec_write(chip, 0x4E,
3392                                       snd_cs46xx_codec_read(chip, 0x4E) | 0x0180);
3393                /* Now wake the AMP (this might be backwards) */
3394                snd_cs46xx_codec_write(chip, 0x54,
3395                                       snd_cs46xx_codec_read(chip, 0x54) & ~0x0180);
3396        } else {
3397                snd_cs46xx_codec_write(chip, 0x54,
3398                                       snd_cs46xx_codec_read(chip, 0x54) | 0x0180);
3399        }
3400}
3401#endif
3402
3403
3404/*
3405 *      Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
3406 *      whenever we need to beat on the chip.
3407 *
3408 *      The original idea and code for this hack comes from David Kaiser at
3409 *      Linuxcare. Perhaps one day Crystal will document their chips well
3410 *      enough to make them useful.
3411 */
3412 
3413static void clkrun_hack(struct snd_cs46xx *chip, int change)
3414{
3415        u16 control, nval;
3416        
3417        if (!chip->acpi_port)
3418                return;
3419
3420        chip->amplifier += change;
3421        
3422        /* Read ACPI port */    
3423        nval = control = inw(chip->acpi_port + 0x10);
3424
3425        /* Flip CLKRUN off while running */
3426        if (! chip->amplifier)
3427                nval |= 0x2000;
3428        else
3429                nval &= ~0x2000;
3430        if (nval != control)
3431                outw(nval, chip->acpi_port + 0x10);
3432}
3433
3434        
3435/*
3436 * detect intel piix4
3437 */
3438static void clkrun_init(struct snd_cs46xx *chip)
3439{
3440        struct pci_dev *pdev;
3441        u8 pp;
3442
3443        chip->acpi_port = 0;
3444        
3445        pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
3446                PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
3447        if (pdev == NULL)
3448                return;         /* Not a thinkpad thats for sure */
3449
3450        /* Find the control port */             
3451        pci_read_config_byte(pdev, 0x41, &pp);
3452        chip->acpi_port = pp << 8;
3453        pci_dev_put(pdev);
3454}
3455
3456
3457/*
3458 * Card subid table
3459 */
3460 
3461struct cs_card_type
3462{
3463        u16 vendor;
3464        u16 id;
3465        char *name;
3466        void (*init)(struct snd_cs46xx *);
3467        void (*amp)(struct snd_cs46xx *, int);
3468        void (*active)(struct snd_cs46xx *, int);
3469        void (*mixer_init)(struct snd_cs46xx *);
3470};
3471
3472static struct cs_card_type __devinitdata cards[] = {
3473        {
3474                .vendor = 0x1489,
3475                .id = 0x7001,
3476                .name = "Genius Soundmaker 128 value",
3477                /* nothing special */
3478        },
3479        {
3480                .vendor = 0x5053,
3481                .id = 0x3357,
3482                .name = "Voyetra",
3483                .amp = amp_voyetra,
3484                .mixer_init = voyetra_mixer_init,
3485        },
3486        {
3487                .vendor = 0x1071,
3488                .id = 0x6003,
3489                .name = "Mitac MI6020/21",
3490                .amp = amp_voyetra,
3491        },
3492        {
3493                .vendor = 0x14AF,
3494                .id = 0x0050,
3495                .name = "Hercules Game Theatre XP",
3496                .amp = amp_hercules,
3497                .mixer_init = hercules_mixer_init,
3498        },
3499        {
3500                .vendor = 0x1681,
3501                .id = 0x0050,
3502                .name = "Hercules Game Theatre XP",
3503                .amp = amp_hercules,
3504                .mixer_init = hercules_mixer_init,
3505        },
3506        {
3507                .vendor = 0x1681,
3508                .id = 0x0051,
3509                .name = "Hercules Game Theatre XP",
3510                .amp = amp_hercules,
3511                .mixer_init = hercules_mixer_init,
3512
3513        },
3514        {
3515                .vendor = 0x1681,
3516                .id = 0x0052,
3517                .name = "Hercules Game Theatre XP",
3518                .amp = amp_hercules,
3519                .mixer_init = hercules_mixer_init,
3520        },
3521        {
3522                .vendor = 0x1681,
3523                .id = 0x0053,
3524                .name = "Hercules Game Theatre XP",
3525                .amp = amp_hercules,
3526                .mixer_init = hercules_mixer_init,
3527        },
3528        {
3529                .vendor = 0x1681,
3530                .id = 0x0054,
3531                .name = "Hercules Game Theatre XP",
3532                .amp = amp_hercules,
3533                .mixer_init = hercules_mixer_init,
3534        },
3535        /* Teratec */
3536        {
3537                .vendor = 0x153b,
3538                .id = 0x1136,
3539                .name = "Terratec SiXPack 5.1",
3540        },
3541        /* Not sure if the 570 needs the clkrun hack */
3542        {
3543                .vendor = PCI_VENDOR_ID_IBM,
3544                .id = 0x0132,
3545                .name = "Thinkpad 570",
3546                .init = clkrun_init,
3547                .active = clkrun_hack,
3548        },
3549        {
3550                .vendor = PCI_VENDOR_ID_IBM,
3551                .id = 0x0153,
3552                .name = "Thinkpad 600X/A20/T20",
3553                .init = clkrun_init,
3554                .active = clkrun_hack,
3555        },
3556        {
3557                .vendor = PCI_VENDOR_ID_IBM,
3558                .id = 0x1010,
3559                .name = "Thinkpad 600E (unsupported)",
3560        },
3561        {} /* terminator */
3562};
3563
3564
3565/*
3566 * APM support
3567 */
3568#ifdef CONFIG_PM
3569static unsigned int saved_regs[] = {
3570        BA0_ACOSV,
3571        BA0_ASER_FADDR,
3572        BA0_ASER_MASTER,
3573        BA1_PVOL,
3574        BA1_CVOL,
3575};
3576
3577int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
3578{
3579        struct snd_card *card = pci_get_drvdata(pci);
3580        struct snd_cs46xx *chip = card->private_data;
3581        int i, amp_saved;
3582
3583        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
3584        chip->in_suspend = 1;
3585        snd_pcm_suspend_all(chip->pcm);
3586        // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
3587        // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
3588
3589        snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
3590        snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
3591
3592        /* save some registers */
3593        for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
3594                chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]);
3595
3596        amp_saved = chip->amplifier;
3597        /* turn off amp */
3598        chip->amplifier_ctrl(chip, -chip->amplifier);
3599        snd_cs46xx_hw_stop(chip);
3600        /* disable CLKRUN */
3601        chip->active_ctrl(chip, -chip->amplifier);
3602        chip->amplifier = amp_saved; /* restore the status */
3603
3604        pci_disable_device(pci);
3605        pci_save_state(pci);
3606        pci_set_power_state(pci, pci_choose_state(pci, state));
3607        return 0;
3608}
3609
3610int snd_cs46xx_resume(struct pci_dev *pci)
3611{
3612        struct snd_card *card = pci_get_drvdata(pci);
3613        struct snd_cs46xx *chip = card->private_data;
3614        int i, amp_saved;
3615
3616        pci_set_power_state(pci, PCI_D0);
3617        pci_restore_state(pci);
3618        if (pci_enable_device(pci) < 0) {
3619                printk(KERN_ERR "cs46xx: pci_enable_device failed, "
3620                       "disabling device\n");
3621                snd_card_disconnect(card);
3622                return -EIO;
3623        }
3624        pci_set_master(pci);
3625
3626        amp_saved = chip->amplifier;
3627        chip->amplifier = 0;
3628        chip->active_ctrl(chip, 1); /* force to on */
3629
3630        snd_cs46xx_chip_init(chip);
3631
3632        snd_cs46xx_reset(chip);
3633#ifdef CONFIG_SND_CS46XX_NEW_DSP
3634        cs46xx_dsp_resume(chip);
3635        /* restore some registers */
3636        for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
3637                snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]);
3638#else
3639        snd_cs46xx_download_image(chip);
3640#endif
3641
3642#if 0
3643        snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 
3644                               chip->ac97_general_purpose);
3645        snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL, 
3646                               chip->ac97_powerdown);
3647        mdelay(10);
3648        snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN,
3649                               chip->ac97_powerdown);
3650        mdelay(5);
3651#endif
3652
3653        snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
3654        snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
3655
3656        /* reset playback/capture */
3657        snd_cs46xx_set_play_sample_rate(chip, 8000);
3658        snd_cs46xx_set_capture_sample_rate(chip, 8000);
3659        snd_cs46xx_proc_start(chip);
3660
3661        cs46xx_enable_stream_irqs(chip);
3662
3663        if (amp_saved)
3664                chip->amplifier_ctrl(chip, 1); /* turn amp on */
3665        else
3666                chip->active_ctrl(chip, -1); /* disable CLKRUN */
3667        chip->amplifier = amp_saved;
3668        chip->in_suspend = 0;
3669        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
3670        return 0;
3671}
3672#endif /* CONFIG_PM */
3673
3674
3675/*
3676 */
3677
3678int __devinit snd_cs46xx_create(struct snd_card *card,
3679                      struct pci_dev * pci,
3680                      int external_amp, int thinkpad,
3681                      struct snd_cs46xx ** rchip)
3682{
3683        struct snd_cs46xx *chip;
3684        int err, idx;
3685        struct snd_cs46xx_region *region;
3686        struct cs_card_type *cp;
3687        u16 ss_card, ss_vendor;
3688        static struct snd_device_ops ops = {
3689                .dev_free =     snd_cs46xx_dev_free,
3690        };
3691        
3692        *rchip = NULL;
3693
3694        /* enable PCI device */
3695        if ((err = pci_enable_device(pci)) < 0)
3696                return err;
3697
3698        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
3699        if (chip == NULL) {
3700                pci_disable_device(pci);
3701                return -ENOMEM;
3702        }
3703        spin_lock_init(&chip->reg_lock);
3704#ifdef CONFIG_SND_CS46XX_NEW_DSP
3705        mutex_init(&chip->spos_mutex);
3706#endif
3707        chip->card = card;
3708        chip->pci = pci;
3709        chip->irq = -1;
3710        chip->ba0_addr = pci_resource_start(pci, 0);
3711        chip->ba1_addr = pci_resource_start(pci, 1);
3712        if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
3713            chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) {
3714                snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
3715                           chip->ba0_addr, chip->ba1_addr);
3716                snd_cs46xx_free(chip);
3717                return -ENOMEM;
3718        }
3719
3720        region = &chip->region.name.ba0;
3721        strcpy(region->name, "CS46xx_BA0");
3722        region->base = chip->ba0_addr;
3723        region->size = CS46XX_BA0_SIZE;
3724
3725        region = &chip->region.name.data0;
3726        strcpy(region->name, "CS46xx_BA1_data0");
3727        region->base = chip->ba1_addr + BA1_SP_DMEM0;
3728        region->size = CS46XX_BA1_DATA0_SIZE;
3729
3730        region = &chip->region.name.data1;
3731        strcpy(region->name, "CS46xx_BA1_data1");
3732        region->base = chip->ba1_addr + BA1_SP_DMEM1;
3733        region->size = CS46XX_BA1_DATA1_SIZE;
3734
3735        region = &chip->region.name.pmem;
3736        strcpy(region->name, "CS46xx_BA1_pmem");
3737        region->base = chip->ba1_addr + BA1_SP_PMEM;
3738        region->size = CS46XX_BA1_PRG_SIZE;
3739
3740        region = &chip->region.name.reg;
3741        strcpy(region->name, "CS46xx_BA1_reg");
3742        region->base = chip->ba1_addr + BA1_SP_REG;
3743        region->size = CS46XX_BA1_REG_SIZE;
3744
3745        /* set up amp and clkrun hack */
3746        pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
3747        pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);
3748
3749        for (cp = &cards[0]; cp->name; cp++) {
3750                if (cp->vendor == ss_vendor && cp->id == ss_card) {
3751                        snd_printdd ("hack for %s enabled\n", cp->name);
3752
3753                        chip->amplifier_ctrl = cp->amp;
3754                        chip->active_ctrl = cp->active;
3755                        chip->mixer_init = cp->mixer_init;
3756
3757                        if (cp->init)
3758                                cp->init(chip);
3759                        break;
3760                }
3761        }
3762
3763        if (external_amp) {
3764                snd_printk(KERN_INFO "Crystal EAPD support forced on.\n");
3765                chip->amplifier_ctrl = amp_voyetra;
3766        }
3767
3768        if (thinkpad) {
3769                snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n");
3770                chip->active_ctrl = clkrun_hack;
3771                clkrun_init(chip);
3772        }
3773        
3774        if (chip->amplifier_ctrl == NULL)
3775                chip->amplifier_ctrl = amp_none;
3776        if (chip->active_ctrl == NULL)
3777                chip->active_ctrl = amp_none;
3778
3779        chip->active_ctrl(chip, 1); /* enable CLKRUN */
3780
3781        pci_set_master(pci);
3782
3783        for (idx = 0; idx < 5; idx++) {
3784                region = &chip->region.idx[idx];
3785                if ((region->resource = request_mem_region(region->base, region->size,
3786                                                           region->name)) == NULL) {
3787                        snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n",
3788                                   region->base, region->base + region->size - 1);
3789                        snd_cs46xx_free(chip);
3790                        return -EBUSY;
3791                }
3792                region->remap_addr = ioremap_nocache(region->base, region->size);
3793                if (region->remap_addr == NULL) {
3794                        snd_printk(KERN_ERR "%s ioremap problem\n", region->name);
3795                        snd_cs46xx_free(chip);
3796                        return -ENOMEM;
3797                }
3798        }
3799
3800        if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
3801                        "CS46XX", chip)) {
3802                snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
3803                snd_cs46xx_free(chip);
3804                return -EBUSY;
3805        }
3806        chip->irq = pci->irq;
3807
3808#ifdef CONFIG_SND_CS46XX_NEW_DSP
3809        chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
3810        if (chip->dsp_spos_instance == NULL) {
3811                snd_cs46xx_free(chip);
3812                return -ENOMEM;
3813        }
3814#endif
3815
3816        err = snd_cs46xx_chip_init(chip);
3817        if (err < 0) {
3818                snd_cs46xx_free(chip);
3819                return err;
3820        }
3821
3822        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
3823                snd_cs46xx_free(chip);
3824                return err;
3825        }
3826        
3827        snd_cs46xx_proc_init(card, chip);
3828
3829#ifdef CONFIG_PM
3830        chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) *
3831                                   ARRAY_SIZE(saved_regs), GFP_KERNEL);
3832        if (!chip->saved_regs) {
3833                snd_cs46xx_free(chip);
3834                return -ENOMEM;
3835        }
3836#endif
3837
3838        chip->active_ctrl(chip, -1); /* disable CLKRUN */
3839
3840        snd_card_set_dev(card, &pci->dev);
3841
3842        *rchip = chip;
3843        return 0;
3844}
3845
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.