linux/sound/isa/wss/wss_lib.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   3 *  Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
   4 *
   5 *  Bugs:
   6 *     - sometimes record brokes playback with WSS portion of
   7 *       Yamaha OPL3-SA3 chip
   8 *     - CS4231 (GUS MAX) - still trouble with occasional noises
   9 *                        - broken initialization?
  10 *
  11 *   This program is free software; you can redistribute it and/or modify
  12 *   it under the terms of the GNU General Public License as published by
  13 *   the Free Software Foundation; either version 2 of the License, or
  14 *   (at your option) any later version.
  15 *
  16 *   This program is distributed in the hope that it will be useful,
  17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 *   GNU General Public License for more details.
  20 *
  21 *   You should have received a copy of the GNU General Public License
  22 *   along with this program; if not, write to the Free Software
  23 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  24 *
  25 */
  26
  27#include <linux/delay.h>
  28#include <linux/pm.h>
  29#include <linux/init.h>
  30#include <linux/interrupt.h>
  31#include <linux/slab.h>
  32#include <linux/ioport.h>
  33#include <sound/core.h>
  34#include <sound/wss.h>
  35#include <sound/pcm_params.h>
  36#include <sound/tlv.h>
  37
  38#include <asm/io.h>
  39#include <asm/dma.h>
  40#include <asm/irq.h>
  41
  42MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  43MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
  44MODULE_LICENSE("GPL");
  45
  46#if 0
  47#define SNDRV_DEBUG_MCE
  48#endif
  49
  50/*
  51 *  Some variables
  52 */
  53
  54static unsigned char freq_bits[14] = {
  55        /* 5510 */      0x00 | CS4231_XTAL2,
  56        /* 6620 */      0x0E | CS4231_XTAL2,
  57        /* 8000 */      0x00 | CS4231_XTAL1,
  58        /* 9600 */      0x0E | CS4231_XTAL1,
  59        /* 11025 */     0x02 | CS4231_XTAL2,
  60        /* 16000 */     0x02 | CS4231_XTAL1,
  61        /* 18900 */     0x04 | CS4231_XTAL2,
  62        /* 22050 */     0x06 | CS4231_XTAL2,
  63        /* 27042 */     0x04 | CS4231_XTAL1,
  64        /* 32000 */     0x06 | CS4231_XTAL1,
  65        /* 33075 */     0x0C | CS4231_XTAL2,
  66        /* 37800 */     0x08 | CS4231_XTAL2,
  67        /* 44100 */     0x0A | CS4231_XTAL2,
  68        /* 48000 */     0x0C | CS4231_XTAL1
  69};
  70
  71static unsigned int rates[14] = {
  72        5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
  73        27042, 32000, 33075, 37800, 44100, 48000
  74};
  75
  76static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
  77        .count = ARRAY_SIZE(rates),
  78        .list = rates,
  79        .mask = 0,
  80};
  81
  82static int snd_wss_xrate(struct snd_pcm_runtime *runtime)
  83{
  84        return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
  85                                          &hw_constraints_rates);
  86}
  87
  88static unsigned char snd_wss_original_image[32] =
  89{
  90        0x00,                   /* 00/00 - lic */
  91        0x00,                   /* 01/01 - ric */
  92        0x9f,                   /* 02/02 - la1ic */
  93        0x9f,                   /* 03/03 - ra1ic */
  94        0x9f,                   /* 04/04 - la2ic */
  95        0x9f,                   /* 05/05 - ra2ic */
  96        0xbf,                   /* 06/06 - loc */
  97        0xbf,                   /* 07/07 - roc */
  98        0x20,                   /* 08/08 - pdfr */
  99        CS4231_AUTOCALIB,       /* 09/09 - ic */
 100        0x00,                   /* 0a/10 - pc */
 101        0x00,                   /* 0b/11 - ti */
 102        CS4231_MODE2,           /* 0c/12 - mi */
 103        0xfc,                   /* 0d/13 - lbc */
 104        0x00,                   /* 0e/14 - pbru */
 105        0x00,                   /* 0f/15 - pbrl */
 106        0x80,                   /* 10/16 - afei */
 107        0x01,                   /* 11/17 - afeii */
 108        0x9f,                   /* 12/18 - llic */
 109        0x9f,                   /* 13/19 - rlic */
 110        0x00,                   /* 14/20 - tlb */
 111        0x00,                   /* 15/21 - thb */
 112        0x00,                   /* 16/22 - la3mic/reserved */
 113        0x00,                   /* 17/23 - ra3mic/reserved */
 114        0x00,                   /* 18/24 - afs */
 115        0x00,                   /* 19/25 - lamoc/version */
 116        0xcf,                   /* 1a/26 - mioc */
 117        0x00,                   /* 1b/27 - ramoc/reserved */
 118        0x20,                   /* 1c/28 - cdfr */
 119        0x00,                   /* 1d/29 - res4 */
 120        0x00,                   /* 1e/30 - cbru */
 121        0x00,                   /* 1f/31 - cbrl */
 122};
 123
 124static unsigned char snd_opti93x_original_image[32] =
 125{
 126        0x00,           /* 00/00 - l_mixout_outctrl */
 127        0x00,           /* 01/01 - r_mixout_outctrl */
 128        0x88,           /* 02/02 - l_cd_inctrl */
 129        0x88,           /* 03/03 - r_cd_inctrl */
 130        0x88,           /* 04/04 - l_a1/fm_inctrl */
 131        0x88,           /* 05/05 - r_a1/fm_inctrl */
 132        0x80,           /* 06/06 - l_dac_inctrl */
 133        0x80,           /* 07/07 - r_dac_inctrl */
 134        0x00,           /* 08/08 - ply_dataform_reg */
 135        0x00,           /* 09/09 - if_conf */
 136        0x00,           /* 0a/10 - pin_ctrl */
 137        0x00,           /* 0b/11 - err_init_reg */
 138        0x0a,           /* 0c/12 - id_reg */
 139        0x00,           /* 0d/13 - reserved */
 140        0x00,           /* 0e/14 - ply_upcount_reg */
 141        0x00,           /* 0f/15 - ply_lowcount_reg */
 142        0x88,           /* 10/16 - reserved/l_a1_inctrl */
 143        0x88,           /* 11/17 - reserved/r_a1_inctrl */
 144        0x88,           /* 12/18 - l_line_inctrl */
 145        0x88,           /* 13/19 - r_line_inctrl */
 146        0x88,           /* 14/20 - l_mic_inctrl */
 147        0x88,           /* 15/21 - r_mic_inctrl */
 148        0x80,           /* 16/22 - l_out_outctrl */
 149        0x80,           /* 17/23 - r_out_outctrl */
 150        0x00,           /* 18/24 - reserved */
 151        0x00,           /* 19/25 - reserved */
 152        0x00,           /* 1a/26 - reserved */
 153        0x00,           /* 1b/27 - reserved */
 154        0x00,           /* 1c/28 - cap_dataform_reg */
 155        0x00,           /* 1d/29 - reserved */
 156        0x00,           /* 1e/30 - cap_upcount_reg */
 157        0x00            /* 1f/31 - cap_lowcount_reg */
 158};
 159
 160/*
 161 *  Basic I/O functions
 162 */
 163
 164static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val)
 165{
 166        outb(val, chip->port + offset);
 167}
 168
 169static inline u8 wss_inb(struct snd_wss *chip, u8 offset)
 170{
 171        return inb(chip->port + offset);
 172}
 173
 174static void snd_wss_wait(struct snd_wss *chip)
 175{
 176        int timeout;
 177
 178        for (timeout = 250;
 179             timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
 180             timeout--)
 181                udelay(100);
 182}
 183
 184static void snd_wss_outm(struct snd_wss *chip, unsigned char reg,
 185                            unsigned char mask, unsigned char value)
 186{
 187        unsigned char tmp = (chip->image[reg] & mask) | value;
 188
 189        snd_wss_wait(chip);
 190#ifdef CONFIG_SND_DEBUG
 191        if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
 192                snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 193#endif
 194        chip->image[reg] = tmp;
 195        if (!chip->calibrate_mute) {
 196                wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
 197                wmb();
 198                wss_outb(chip, CS4231P(REG), tmp);
 199                mb();
 200        }
 201}
 202
 203static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
 204                         unsigned char value)
 205{
 206        int timeout;
 207
 208        for (timeout = 250;
 209             timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
 210             timeout--)
 211                udelay(10);
 212        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
 213        wss_outb(chip, CS4231P(REG), value);
 214        mb();
 215}
 216
 217void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value)
 218{
 219        snd_wss_wait(chip);
 220#ifdef CONFIG_SND_DEBUG
 221        if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
 222                snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 223#endif
 224        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
 225        wss_outb(chip, CS4231P(REG), value);
 226        chip->image[reg] = value;
 227        mb();
 228        snd_printdd("codec out - reg 0x%x = 0x%x\n",
 229                        chip->mce_bit | reg, value);
 230}
 231EXPORT_SYMBOL(snd_wss_out);
 232
 233unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg)
 234{
 235        snd_wss_wait(chip);
 236#ifdef CONFIG_SND_DEBUG
 237        if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
 238                snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
 239#endif
 240        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
 241        mb();
 242        return wss_inb(chip, CS4231P(REG));
 243}
 244EXPORT_SYMBOL(snd_wss_in);
 245
 246void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg,
 247                        unsigned char val)
 248{
 249        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
 250        wss_outb(chip, CS4231P(REG),
 251                 reg | (chip->image[CS4236_EXT_REG] & 0x01));
 252        wss_outb(chip, CS4231P(REG), val);
 253        chip->eimage[CS4236_REG(reg)] = val;
 254#if 0
 255        printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
 256#endif
 257}
 258EXPORT_SYMBOL(snd_cs4236_ext_out);
 259
 260unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg)
 261{
 262        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
 263        wss_outb(chip, CS4231P(REG),
 264                 reg | (chip->image[CS4236_EXT_REG] & 0x01));
 265#if 1
 266        return wss_inb(chip, CS4231P(REG));
 267#else
 268        {
 269                unsigned char res;
 270                res = wss_inb(chip, CS4231P(REG));
 271                printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
 272                return res;
 273        }
 274#endif
 275}
 276EXPORT_SYMBOL(snd_cs4236_ext_in);
 277
 278#if 0
 279
 280static void snd_wss_debug(struct snd_wss *chip)
 281{
 282        printk(KERN_DEBUG
 283                "CS4231 REGS:      INDEX = 0x%02x  "
 284                "                 STATUS = 0x%02x\n",
 285                                        wss_inb(chip, CS4231P(REGSEL)),
 286                                        wss_inb(chip, CS4231P(STATUS)));
 287        printk(KERN_DEBUG
 288                "  0x00: left input      = 0x%02x  "
 289                "  0x10: alt 1 (CFIG 2)  = 0x%02x\n",
 290                                        snd_wss_in(chip, 0x00),
 291                                        snd_wss_in(chip, 0x10));
 292        printk(KERN_DEBUG
 293                "  0x01: right input     = 0x%02x  "
 294                "  0x11: alt 2 (CFIG 3)  = 0x%02x\n",
 295                                        snd_wss_in(chip, 0x01),
 296                                        snd_wss_in(chip, 0x11));
 297        printk(KERN_DEBUG
 298                "  0x02: GF1 left input  = 0x%02x  "
 299                "  0x12: left line in    = 0x%02x\n",
 300                                        snd_wss_in(chip, 0x02),
 301                                        snd_wss_in(chip, 0x12));
 302        printk(KERN_DEBUG
 303                "  0x03: GF1 right input = 0x%02x  "
 304                "  0x13: right line in   = 0x%02x\n",
 305                                        snd_wss_in(chip, 0x03),
 306                                        snd_wss_in(chip, 0x13));
 307        printk(KERN_DEBUG
 308                "  0x04: CD left input   = 0x%02x  "
 309                "  0x14: timer low       = 0x%02x\n",
 310                                        snd_wss_in(chip, 0x04),
 311                                        snd_wss_in(chip, 0x14));
 312        printk(KERN_DEBUG
 313                "  0x05: CD right input  = 0x%02x  "
 314                "  0x15: timer high      = 0x%02x\n",
 315                                        snd_wss_in(chip, 0x05),
 316                                        snd_wss_in(chip, 0x15));
 317        printk(KERN_DEBUG
 318                "  0x06: left output     = 0x%02x  "
 319                "  0x16: left MIC (PnP)  = 0x%02x\n",
 320                                        snd_wss_in(chip, 0x06),
 321                                        snd_wss_in(chip, 0x16));
 322        printk(KERN_DEBUG
 323                "  0x07: right output    = 0x%02x  "
 324                "  0x17: right MIC (PnP) = 0x%02x\n",
 325                                        snd_wss_in(chip, 0x07),
 326                                        snd_wss_in(chip, 0x17));
 327        printk(KERN_DEBUG
 328                "  0x08: playback format = 0x%02x  "
 329                "  0x18: IRQ status      = 0x%02x\n",
 330                                        snd_wss_in(chip, 0x08),
 331                                        snd_wss_in(chip, 0x18));
 332        printk(KERN_DEBUG
 333                "  0x09: iface (CFIG 1)  = 0x%02x  "
 334                "  0x19: left line out   = 0x%02x\n",
 335                                        snd_wss_in(chip, 0x09),
 336                                        snd_wss_in(chip, 0x19));
 337        printk(KERN_DEBUG
 338                "  0x0a: pin control     = 0x%02x  "
 339                "  0x1a: mono control    = 0x%02x\n",
 340                                        snd_wss_in(chip, 0x0a),
 341                                        snd_wss_in(chip, 0x1a));
 342        printk(KERN_DEBUG
 343                "  0x0b: init & status   = 0x%02x  "
 344                "  0x1b: right line out  = 0x%02x\n",
 345                                        snd_wss_in(chip, 0x0b),
 346                                        snd_wss_in(chip, 0x1b));
 347        printk(KERN_DEBUG
 348                "  0x0c: revision & mode = 0x%02x  "
 349                "  0x1c: record format   = 0x%02x\n",
 350                                        snd_wss_in(chip, 0x0c),
 351                                        snd_wss_in(chip, 0x1c));
 352        printk(KERN_DEBUG
 353                "  0x0d: loopback        = 0x%02x  "
 354                "  0x1d: var freq (PnP)  = 0x%02x\n",
 355                                        snd_wss_in(chip, 0x0d),
 356                                        snd_wss_in(chip, 0x1d));
 357        printk(KERN_DEBUG
 358                "  0x0e: ply upr count   = 0x%02x  "
 359                "  0x1e: ply lwr count   = 0x%02x\n",
 360                                        snd_wss_in(chip, 0x0e),
 361                                        snd_wss_in(chip, 0x1e));
 362        printk(KERN_DEBUG
 363                "  0x0f: rec upr count   = 0x%02x  "
 364                "  0x1f: rec lwr count   = 0x%02x\n",
 365                                        snd_wss_in(chip, 0x0f),
 366                                        snd_wss_in(chip, 0x1f));
 367}
 368
 369#endif
 370
 371/*
 372 *  CS4231 detection / MCE routines
 373 */
 374
 375static void snd_wss_busy_wait(struct snd_wss *chip)
 376{
 377        int timeout;
 378
 379        /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
 380        for (timeout = 5; timeout > 0; timeout--)
 381                wss_inb(chip, CS4231P(REGSEL));
 382        /* end of cleanup sequence */
 383        for (timeout = 25000;
 384             timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
 385             timeout--)
 386                udelay(10);
 387}
 388
 389void snd_wss_mce_up(struct snd_wss *chip)
 390{
 391        unsigned long flags;
 392        int timeout;
 393
 394        snd_wss_wait(chip);
 395#ifdef CONFIG_SND_DEBUG
 396        if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
 397                snd_printk("mce_up - auto calibration time out (0)\n");
 398#endif
 399        spin_lock_irqsave(&chip->reg_lock, flags);
 400        chip->mce_bit |= CS4231_MCE;
 401        timeout = wss_inb(chip, CS4231P(REGSEL));
 402        if (timeout == 0x80)
 403                snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
 404        if (!(timeout & CS4231_MCE))
 405                wss_outb(chip, CS4231P(REGSEL),
 406                         chip->mce_bit | (timeout & 0x1f));
 407        spin_unlock_irqrestore(&chip->reg_lock, flags);
 408}
 409EXPORT_SYMBOL(snd_wss_mce_up);
 410
 411void snd_wss_mce_down(struct snd_wss *chip)
 412{
 413        unsigned long flags;
 414        unsigned long end_time;
 415        int timeout;
 416        int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
 417
 418        snd_wss_busy_wait(chip);
 419
 420#ifdef CONFIG_SND_DEBUG
 421        if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
 422                snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
 423#endif
 424        spin_lock_irqsave(&chip->reg_lock, flags);
 425        chip->mce_bit &= ~CS4231_MCE;
 426        timeout = wss_inb(chip, CS4231P(REGSEL));
 427        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
 428        spin_unlock_irqrestore(&chip->reg_lock, flags);
 429        if (timeout == 0x80)
 430                snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
 431        if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
 432                return;
 433
 434        /*
 435         * Wait for (possible -- during init auto-calibration may not be set)
 436         * calibration process to start. Needs upto 5 sample periods on AD1848
 437         * which at the slowest possible rate of 5.5125 kHz means 907 us.
 438         */
 439        msleep(1);
 440
 441        snd_printdd("(1) jiffies = %lu\n", jiffies);
 442
 443        /* check condition up to 250 ms */
 444        end_time = jiffies + msecs_to_jiffies(250);
 445        while (snd_wss_in(chip, CS4231_TEST_INIT) &
 446                CS4231_CALIB_IN_PROGRESS) {
 447
 448                if (time_after(jiffies, end_time)) {
 449                        snd_printk(KERN_ERR "mce_down - "
 450                                        "auto calibration time out (2)\n");
 451                        return;
 452                }
 453                msleep(1);
 454        }
 455
 456        snd_printdd("(2) jiffies = %lu\n", jiffies);
 457
 458        /* check condition up to 100 ms */
 459        end_time = jiffies + msecs_to_jiffies(100);
 460        while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
 461                if (time_after(jiffies, end_time)) {
 462                        snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
 463                        return;
 464                }
 465                msleep(1);
 466        }
 467
 468        snd_printdd("(3) jiffies = %lu\n", jiffies);
 469        snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL)));
 470}
 471EXPORT_SYMBOL(snd_wss_mce_down);
 472
 473static unsigned int snd_wss_get_count(unsigned char format, unsigned int size)
 474{
 475        switch (format & 0xe0) {
 476        case CS4231_LINEAR_16:
 477        case CS4231_LINEAR_16_BIG:
 478                size >>= 1;
 479                break;
 480        case CS4231_ADPCM_16:
 481                return size >> 2;
 482        }
 483        if (format & CS4231_STEREO)
 484                size >>= 1;
 485        return size;
 486}
 487
 488static int snd_wss_trigger(struct snd_pcm_substream *substream,
 489                           int cmd)
 490{
 491        struct snd_wss *chip = snd_pcm_substream_chip(substream);
 492        int result = 0;
 493        unsigned int what;
 494        struct snd_pcm_substream *s;
 495        int do_start;
 496
 497        switch (cmd) {
 498        case SNDRV_PCM_TRIGGER_START:
 499        case SNDRV_PCM_TRIGGER_RESUME:
 500                do_start = 1; break;
 501        case SNDRV_PCM_TRIGGER_STOP:
 502        case SNDRV_PCM_TRIGGER_SUSPEND:
 503                do_start = 0; break;
 504        default:
 505                return -EINVAL;
 506        }
 507
 508        what = 0;
 509        snd_pcm_group_for_each_entry(s, substream) {
 510                if (s == chip->playback_substream) {
 511                        what |= CS4231_PLAYBACK_ENABLE;
 512                        snd_pcm_trigger_done(s, substream);
 513                } else if (s == chip->capture_substream) {
 514                        what |= CS4231_RECORD_ENABLE;
 515                        snd_pcm_trigger_done(s, substream);
 516                }
 517        }
 518        spin_lock(&chip->reg_lock);
 519        if (do_start) {
 520                chip->image[CS4231_IFACE_CTRL] |= what;
 521                if (chip->trigger)
 522                        chip->trigger(chip, what, 1);
 523        } else {
 524                chip->image[CS4231_IFACE_CTRL] &= ~what;
 525                if (chip->trigger)
 526                        chip->trigger(chip, what, 0);
 527        }
 528        snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
 529        spin_unlock(&chip->reg_lock);
 530#if 0
 531        snd_wss_debug(chip);
 532#endif
 533        return result;
 534}
 535
 536/*
 537 *  CODEC I/O
 538 */
 539
 540static unsigned char snd_wss_get_rate(unsigned int rate)
 541{
 542        int i;
 543
 544        for (i = 0; i < ARRAY_SIZE(rates); i++)
 545                if (rate == rates[i])
 546                        return freq_bits[i];
 547        // snd_BUG();
 548        return freq_bits[ARRAY_SIZE(rates) - 1];
 549}
 550
 551static unsigned char snd_wss_get_format(struct snd_wss *chip,
 552                                        int format,
 553                                        int channels)
 554{
 555        unsigned char rformat;
 556
 557        rformat = CS4231_LINEAR_8;
 558        switch (format) {
 559        case SNDRV_PCM_FORMAT_MU_LAW:   rformat = CS4231_ULAW_8; break;
 560        case SNDRV_PCM_FORMAT_A_LAW:    rformat = CS4231_ALAW_8; break;
 561        case SNDRV_PCM_FORMAT_S16_LE:   rformat = CS4231_LINEAR_16; break;
 562        case SNDRV_PCM_FORMAT_S16_BE:   rformat = CS4231_LINEAR_16_BIG; break;
 563        case SNDRV_PCM_FORMAT_IMA_ADPCM:        rformat = CS4231_ADPCM_16; break;
 564        }
 565        if (channels > 1)
 566                rformat |= CS4231_STEREO;
 567#if 0
 568        snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
 569#endif
 570        return rformat;
 571}
 572
 573static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
 574{
 575        unsigned long flags;
 576
 577        mute = mute ? 0x80 : 0;
 578        spin_lock_irqsave(&chip->reg_lock, flags);
 579        if (chip->calibrate_mute == mute) {
 580                spin_unlock_irqrestore(&chip->reg_lock, flags);
 581                return;
 582        }
 583        if (!mute) {
 584                snd_wss_dout(chip, CS4231_LEFT_INPUT,
 585                             chip->image[CS4231_LEFT_INPUT]);
 586                snd_wss_dout(chip, CS4231_RIGHT_INPUT,
 587                             chip->image[CS4231_RIGHT_INPUT]);
 588                snd_wss_dout(chip, CS4231_LOOPBACK,
 589                             chip->image[CS4231_LOOPBACK]);
 590        }
 591        snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
 592                     mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
 593        snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
 594                     mute | chip->image[CS4231_AUX1_RIGHT_INPUT]);
 595        snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT,
 596                     mute | chip->image[CS4231_AUX2_LEFT_INPUT]);
 597        snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT,
 598                     mute | chip->image[CS4231_AUX2_RIGHT_INPUT]);
 599        snd_wss_dout(chip, CS4231_LEFT_OUTPUT,
 600                     mute | chip->image[CS4231_LEFT_OUTPUT]);
 601        snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
 602                     mute | chip->image[CS4231_RIGHT_OUTPUT]);
 603        if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
 604                snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
 605                             mute | chip->image[CS4231_LEFT_LINE_IN]);
 606                snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
 607                             mute | chip->image[CS4231_RIGHT_LINE_IN]);
 608                snd_wss_dout(chip, CS4231_MONO_CTRL,
 609                             mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
 610        }
 611        if (chip->hardware == WSS_HW_INTERWAVE) {
 612                snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
 613                             mute | chip->image[CS4231_LEFT_MIC_INPUT]);
 614                snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT,
 615                             mute | chip->image[CS4231_RIGHT_MIC_INPUT]);
 616                snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT,
 617                             mute | chip->image[CS4231_LINE_LEFT_OUTPUT]);
 618                snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT,
 619                             mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]);
 620        }
 621        chip->calibrate_mute = mute;
 622        spin_unlock_irqrestore(&chip->reg_lock, flags);
 623}
 624
 625static void snd_wss_playback_format(struct snd_wss *chip,
 626                                       struct snd_pcm_hw_params *params,
 627                                       unsigned char pdfr)
 628{
 629        unsigned long flags;
 630        int full_calib = 1;
 631
 632        mutex_lock(&chip->mce_mutex);
 633        snd_wss_calibrate_mute(chip, 1);
 634        if (chip->hardware == WSS_HW_CS4231A ||
 635            (chip->hardware & WSS_HW_CS4232_MASK)) {
 636                spin_lock_irqsave(&chip->reg_lock, flags);
 637                if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) {      /* rate is same? */
 638                        snd_wss_out(chip, CS4231_ALT_FEATURE_1,
 639                                    chip->image[CS4231_ALT_FEATURE_1] | 0x10);
 640                        chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
 641                        snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
 642                                    chip->image[CS4231_PLAYBK_FORMAT]);
 643                        snd_wss_out(chip, CS4231_ALT_FEATURE_1,
 644                                    chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
 645                        udelay(100); /* Fixes audible clicks at least on GUS MAX */
 646                        full_calib = 0;
 647                }
 648                spin_unlock_irqrestore(&chip->reg_lock, flags);
 649        }
 650        if (full_calib) {
 651                snd_wss_mce_up(chip);
 652                spin_lock_irqsave(&chip->reg_lock, flags);
 653                if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) {
 654                        if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)
 655                                pdfr = (pdfr & 0xf0) |
 656                                       (chip->image[CS4231_REC_FORMAT] & 0x0f);
 657                } else {
 658                        chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
 659                }
 660                snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr);
 661                spin_unlock_irqrestore(&chip->reg_lock, flags);
 662                if (chip->hardware == WSS_HW_OPL3SA2)
 663                        udelay(100);    /* this seems to help */
 664                snd_wss_mce_down(chip);
 665        }
 666        snd_wss_calibrate_mute(chip, 0);
 667        mutex_unlock(&chip->mce_mutex);
 668}
 669
 670static void snd_wss_capture_format(struct snd_wss *chip,
 671                                   struct snd_pcm_hw_params *params,
 672                                   unsigned char cdfr)
 673{
 674        unsigned long flags;
 675        int full_calib = 1;
 676
 677        mutex_lock(&chip->mce_mutex);
 678        snd_wss_calibrate_mute(chip, 1);
 679        if (chip->hardware == WSS_HW_CS4231A ||
 680            (chip->hardware & WSS_HW_CS4232_MASK)) {
 681                spin_lock_irqsave(&chip->reg_lock, flags);
 682                if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) ||      /* rate is same? */
 683                    (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
 684                        snd_wss_out(chip, CS4231_ALT_FEATURE_1,
 685                                chip->image[CS4231_ALT_FEATURE_1] | 0x20);
 686                        snd_wss_out(chip, CS4231_REC_FORMAT,
 687                                chip->image[CS4231_REC_FORMAT] = cdfr);
 688                        snd_wss_out(chip, CS4231_ALT_FEATURE_1,
 689                                chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
 690                        full_calib = 0;
 691                }
 692                spin_unlock_irqrestore(&chip->reg_lock, flags);
 693        }
 694        if (full_calib) {
 695                snd_wss_mce_up(chip);
 696                spin_lock_irqsave(&chip->reg_lock, flags);
 697                if (chip->hardware != WSS_HW_INTERWAVE &&
 698                    !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
 699                        if (chip->single_dma)
 700                                snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
 701                        else
 702                                snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
 703                                   (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) |
 704                                   (cdfr & 0x0f));
 705                        spin_unlock_irqrestore(&chip->reg_lock, flags);
 706                        snd_wss_mce_down(chip);
 707                        snd_wss_mce_up(chip);
 708                        spin_lock_irqsave(&chip->reg_lock, flags);
 709                }
 710                if (chip->hardware & WSS_HW_AD1848_MASK)
 711                        snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
 712                else
 713                        snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
 714                spin_unlock_irqrestore(&chip->reg_lock, flags);
 715                snd_wss_mce_down(chip);
 716        }
 717        snd_wss_calibrate_mute(chip, 0);
 718        mutex_unlock(&chip->mce_mutex);
 719}
 720
 721/*
 722 *  Timer interface
 723 */
 724
 725static unsigned long snd_wss_timer_resolution(struct snd_timer *timer)
 726{
 727        struct snd_wss *chip = snd_timer_chip(timer);
 728        if (chip->hardware & WSS_HW_CS4236B_MASK)
 729                return 14467;
 730        else
 731                return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
 732}
 733
 734static int snd_wss_timer_start(struct snd_timer *timer)
 735{
 736        unsigned long flags;
 737        unsigned int ticks;
 738        struct snd_wss *chip = snd_timer_chip(timer);
 739        spin_lock_irqsave(&chip->reg_lock, flags);
 740        ticks = timer->sticks;
 741        if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
 742            (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
 743            (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
 744                chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8);
 745                snd_wss_out(chip, CS4231_TIMER_HIGH,
 746                            chip->image[CS4231_TIMER_HIGH]);
 747                chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks;
 748                snd_wss_out(chip, CS4231_TIMER_LOW,
 749                            chip->image[CS4231_TIMER_LOW]);
 750                snd_wss_out(chip, CS4231_ALT_FEATURE_1,
 751                            chip->image[CS4231_ALT_FEATURE_1] |
 752                            CS4231_TIMER_ENABLE);
 753        }
 754        spin_unlock_irqrestore(&chip->reg_lock, flags);
 755        return 0;
 756}
 757
 758static int snd_wss_timer_stop(struct snd_timer *timer)
 759{
 760        unsigned long flags;
 761        struct snd_wss *chip = snd_timer_chip(timer);
 762        spin_lock_irqsave(&chip->reg_lock, flags);
 763        chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;
 764        snd_wss_out(chip, CS4231_ALT_FEATURE_1,
 765                    chip->image[CS4231_ALT_FEATURE_1]);
 766        spin_unlock_irqrestore(&chip->reg_lock, flags);
 767        return 0;
 768}
 769
 770static void snd_wss_init(struct snd_wss *chip)
 771{
 772        unsigned long flags;
 773
 774        snd_wss_mce_down(chip);
 775
 776#ifdef SNDRV_DEBUG_MCE
 777        snd_printk("init: (1)\n");
 778#endif
 779        snd_wss_mce_up(chip);
 780        spin_lock_irqsave(&chip->reg_lock, flags);
 781        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
 782                                            CS4231_PLAYBACK_PIO |
 783                                            CS4231_RECORD_ENABLE |
 784                                            CS4231_RECORD_PIO |
 785                                            CS4231_CALIB_MODE);
 786        chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
 787        snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
 788        spin_unlock_irqrestore(&chip->reg_lock, flags);
 789        snd_wss_mce_down(chip);
 790
 791#ifdef SNDRV_DEBUG_MCE
 792        snd_printk("init: (2)\n");
 793#endif
 794
 795        snd_wss_mce_up(chip);
 796        spin_lock_irqsave(&chip->reg_lock, flags);
 797        snd_wss_out(chip,
 798                    CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
 799        spin_unlock_irqrestore(&chip->reg_lock, flags);
 800        snd_wss_mce_down(chip);
 801
 802#ifdef SNDRV_DEBUG_MCE
 803        snd_printk("init: (3) - afei = 0x%x\n",
 804                   chip->image[CS4231_ALT_FEATURE_1]);
 805#endif
 806
 807        spin_lock_irqsave(&chip->reg_lock, flags);
 808        snd_wss_out(chip, CS4231_ALT_FEATURE_2,
 809                    chip->image[CS4231_ALT_FEATURE_2]);
 810        spin_unlock_irqrestore(&chip->reg_lock, flags);
 811
 812        snd_wss_mce_up(chip);
 813        spin_lock_irqsave(&chip->reg_lock, flags);
 814        snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
 815                    chip->image[CS4231_PLAYBK_FORMAT]);
 816        spin_unlock_irqrestore(&chip->reg_lock, flags);
 817        snd_wss_mce_down(chip);
 818
 819#ifdef SNDRV_DEBUG_MCE
 820        snd_printk("init: (4)\n");
 821#endif
 822
 823        snd_wss_mce_up(chip);
 824        spin_lock_irqsave(&chip->reg_lock, flags);
 825        if (!(chip->hardware & WSS_HW_AD1848_MASK))
 826                snd_wss_out(chip, CS4231_REC_FORMAT,
 827                            chip->image[CS4231_REC_FORMAT]);
 828        spin_unlock_irqrestore(&chip->reg_lock, flags);
 829        snd_wss_mce_down(chip);
 830
 831#ifdef SNDRV_DEBUG_MCE
 832        snd_printk("init: (5)\n");
 833#endif
 834}
 835
 836static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
 837{
 838        unsigned long flags;
 839
 840        mutex_lock(&chip->open_mutex);
 841        if ((chip->mode & mode) ||
 842            ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) {
 843                mutex_unlock(&chip->open_mutex);
 844                return -EAGAIN;
 845        }
 846        if (chip->mode & WSS_MODE_OPEN) {
 847                chip->mode |= mode;
 848                mutex_unlock(&chip->open_mutex);
 849                return 0;
 850        }
 851        /* ok. now enable and ack CODEC IRQ */
 852        spin_lock_irqsave(&chip->reg_lock, flags);
 853        if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
 854                snd_wss_out(chip, CS4231_IRQ_STATUS,
 855                            CS4231_PLAYBACK_IRQ |
 856                            CS4231_RECORD_IRQ |
 857                            CS4231_TIMER_IRQ);
 858                snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
 859        }
 860        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
 861        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
 862        chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
 863        snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
 864        if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
 865                snd_wss_out(chip, CS4231_IRQ_STATUS,
 866                            CS4231_PLAYBACK_IRQ |
 867                            CS4231_RECORD_IRQ |
 868                            CS4231_TIMER_IRQ);
 869                snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
 870        }
 871        spin_unlock_irqrestore(&chip->reg_lock, flags);
 872
 873        chip->mode = mode;
 874        mutex_unlock(&chip->open_mutex);
 875        return 0;
 876}
 877
 878static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
 879{
 880        unsigned long flags;
 881
 882        mutex_lock(&chip->open_mutex);
 883        chip->mode &= ~mode;
 884        if (chip->mode & WSS_MODE_OPEN) {
 885                mutex_unlock(&chip->open_mutex);
 886                return;
 887        }
 888        snd_wss_calibrate_mute(chip, 1);
 889
 890        /* disable IRQ */
 891        spin_lock_irqsave(&chip->reg_lock, flags);
 892        if (!(chip->hardware & WSS_HW_AD1848_MASK))
 893                snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
 894        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
 895        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
 896        chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
 897        snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
 898
 899        /* now disable record & playback */
 900
 901        if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
 902                                               CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
 903                spin_unlock_irqrestore(&chip->reg_lock, flags);
 904                snd_wss_mce_up(chip);
 905                spin_lock_irqsave(&chip->reg_lock, flags);
 906                chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
 907                                                     CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
 908                snd_wss_out(chip, CS4231_IFACE_CTRL,
 909                            chip->image[CS4231_IFACE_CTRL]);
 910                spin_unlock_irqrestore(&chip->reg_lock, flags);
 911                snd_wss_mce_down(chip);
 912                spin_lock_irqsave(&chip->reg_lock, flags);
 913        }
 914
 915        /* clear IRQ again */
 916        if (!(chip->hardware & WSS_HW_AD1848_MASK))
 917                snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
 918        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
 919        wss_outb(chip, CS4231P(STATUS), 0);     /* clear IRQ */
 920        spin_unlock_irqrestore(&chip->reg_lock, flags);
 921
 922        snd_wss_calibrate_mute(chip, 0);
 923
 924        chip->mode = 0;
 925        mutex_unlock(&chip->open_mutex);
 926}
 927
 928/*
 929 *  timer open/close
 930 */
 931
 932static int snd_wss_timer_open(struct snd_timer *timer)
 933{
 934        struct snd_wss *chip = snd_timer_chip(timer);
 935        snd_wss_open(chip, WSS_MODE_TIMER);
 936        return 0;
 937}
 938
 939static int snd_wss_timer_close(struct snd_timer *timer)
 940{
 941        struct snd_wss *chip = snd_timer_chip(timer);
 942        snd_wss_close(chip, WSS_MODE_TIMER);
 943        return 0;
 944}
 945
 946static struct snd_timer_hardware snd_wss_timer_table =
 947{
 948        .flags =        SNDRV_TIMER_HW_AUTO,
 949        .resolution =   9945,
 950        .ticks =        65535,
 951        .open =         snd_wss_timer_open,
 952        .close =        snd_wss_timer_close,
 953        .c_resolution = snd_wss_timer_resolution,
 954        .start =        snd_wss_timer_start,
 955        .stop =         snd_wss_timer_stop,
 956};
 957
 958/*
 959 *  ok.. exported functions..
 960 */
 961
 962static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
 963                                         struct snd_pcm_hw_params *hw_params)
 964{
 965        struct snd_wss *chip = snd_pcm_substream_chip(substream);
 966        unsigned char new_pdfr;
 967        int err;
 968
 969        if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
 970                return err;
 971        new_pdfr = snd_wss_get_format(chip, params_format(hw_params),
 972                                params_channels(hw_params)) |
 973                                snd_wss_get_rate(params_rate(hw_params));
 974        chip->set_playback_format(chip, hw_params, new_pdfr);
 975        return 0;
 976}
 977
 978static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream)
 979{
 980        return snd_pcm_lib_free_pages(substream);
 981}
 982
 983static int snd_wss_playback_prepare(struct snd_pcm_substream *substream)
 984{
 985        struct snd_wss *chip = snd_pcm_substream_chip(substream);
 986        struct snd_pcm_runtime *runtime = substream->runtime;
 987        unsigned long flags;
 988        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
 989        unsigned int count = snd_pcm_lib_period_bytes(substream);
 990
 991        spin_lock_irqsave(&chip->reg_lock, flags);
 992        chip->p_dma_size = size;
 993        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
 994        snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
 995        count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
 996        snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
 997        snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
 998        spin_unlock_irqrestore(&chip->reg_lock, flags);
 999#if 0
1000        snd_wss_debug(chip);
1001#endif
1002        return 0;
1003}
1004
1005static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
1006                                        struct snd_pcm_hw_params *hw_params)
1007{
1008        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1009        unsigned char new_cdfr;
1010        int err;
1011
1012        if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1013                return err;
1014        new_cdfr = snd_wss_get_format(chip, params_format(hw_params),
1015                           params_channels(hw_params)) |
1016                           snd_wss_get_rate(params_rate(hw_params));
1017        chip->set_capture_format(chip, hw_params, new_cdfr);
1018        return 0;
1019}
1020
1021static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream)
1022{
1023        return snd_pcm_lib_free_pages(substream);
1024}
1025
1026static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
1027{
1028        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1029        struct snd_pcm_runtime *runtime = substream->runtime;
1030        unsigned long flags;
1031        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1032        unsigned int count = snd_pcm_lib_period_bytes(substream);
1033
1034        spin_lock_irqsave(&chip->reg_lock, flags);
1035        chip->c_dma_size = size;
1036        chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
1037        snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
1038        if (chip->hardware & WSS_HW_AD1848_MASK)
1039                count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
1040                                          count);
1041        else
1042                count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
1043                                          count);
1044        count--;
1045        if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1046                snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
1047                snd_wss_out(chip, CS4231_PLY_UPR_CNT,
1048                            (unsigned char) (count >> 8));
1049        } else {
1050                snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
1051                snd_wss_out(chip, CS4231_REC_UPR_CNT,
1052                            (unsigned char) (count >> 8));
1053        }
1054        spin_unlock_irqrestore(&chip->reg_lock, flags);
1055        return 0;
1056}
1057
1058void snd_wss_overrange(struct snd_wss *chip)
1059{
1060        unsigned long flags;
1061        unsigned char res;
1062
1063        spin_lock_irqsave(&chip->reg_lock, flags);
1064        res = snd_wss_in(chip, CS4231_TEST_INIT);
1065        spin_unlock_irqrestore(&chip->reg_lock, flags);
1066        if (res & (0x08 | 0x02))        /* detect overrange only above 0dB; may be user selectable? */
1067                chip->capture_substream->runtime->overrange++;
1068}
1069EXPORT_SYMBOL(snd_wss_overrange);
1070
1071irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
1072{
1073        struct snd_wss *chip = dev_id;
1074        unsigned char status;
1075
1076        if (chip->hardware & WSS_HW_AD1848_MASK)
1077                /* pretend it was the only possible irq for AD1848 */
1078                status = CS4231_PLAYBACK_IRQ;
1079        else
1080                status = snd_wss_in(chip, CS4231_IRQ_STATUS);
1081        if (status & CS4231_TIMER_IRQ) {
1082                if (chip->timer)
1083                        snd_timer_interrupt(chip->timer, chip->timer->sticks);
1084        }
1085        if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1086                if (status & CS4231_PLAYBACK_IRQ) {
1087                        if (chip->mode & WSS_MODE_PLAY) {
1088                                if (chip->playback_substream)
1089                                        snd_pcm_period_elapsed(chip->playback_substream);
1090                        }
1091                        if (chip->mode & WSS_MODE_RECORD) {
1092                                if (chip->capture_substream) {
1093                                        snd_wss_overrange(chip);
1094                                        snd_pcm_period_elapsed(chip->capture_substream);
1095                                }
1096                        }
1097                }
1098        } else {
1099                if (status & CS4231_PLAYBACK_IRQ) {
1100                        if (chip->playback_substream)
1101                                snd_pcm_period_elapsed(chip->playback_substream);
1102                }
1103                if (status & CS4231_RECORD_IRQ) {
1104                        if (chip->capture_substream) {
1105                                snd_wss_overrange(chip);
1106                                snd_pcm_period_elapsed(chip->capture_substream);
1107                        }
1108                }
1109        }
1110
1111        spin_lock(&chip->reg_lock);
1112        status = ~CS4231_ALL_IRQS | ~status;
1113        if (chip->hardware & WSS_HW_AD1848_MASK)
1114                wss_outb(chip, CS4231P(STATUS), 0);
1115        else
1116                snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
1117        spin_unlock(&chip->reg_lock);
1118        return IRQ_HANDLED;
1119}
1120EXPORT_SYMBOL(snd_wss_interrupt);
1121
1122static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream)
1123{
1124        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1125        size_t ptr;
1126
1127        if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
1128                return 0;
1129        ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
1130        return bytes_to_frames(substream->runtime, ptr);
1131}
1132
1133static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream)
1134{
1135        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1136        size_t ptr;
1137
1138        if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1139                return 0;
1140        ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
1141        return bytes_to_frames(substream->runtime, ptr);
1142}
1143
1144/*
1145
1146 */
1147
1148static int snd_ad1848_probe(struct snd_wss *chip)
1149{
1150        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
1151        unsigned long flags;
1152        unsigned char r;
1153        unsigned short hardware = 0;
1154        int err = 0;
1155        int i;
1156
1157        while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
1158                if (time_after(jiffies, timeout))
1159                        return -ENODEV;
1160                cond_resched();
1161        }
1162        spin_lock_irqsave(&chip->reg_lock, flags);
1163
1164        /* set CS423x MODE 1 */
1165        snd_wss_dout(chip, CS4231_MISC_INFO, 0);
1166
1167        snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */
1168        r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
1169        if (r != 0x45) {
1170                /* RMGE always high on AD1847 */
1171                if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
1172                        err = -ENODEV;
1173                        goto out;
1174                }
1175                hardware = WSS_HW_AD1847;
1176        } else {
1177                snd_wss_dout(chip, CS4231_LEFT_INPUT,  0xaa);
1178                r = snd_wss_in(chip, CS4231_LEFT_INPUT);
1179                /* L/RMGE always low on AT2320 */
1180                if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
1181                        err = -ENODEV;
1182                        goto out;
1183                }
1184        }
1185
1186        /* clear pending IRQ */
1187        wss_inb(chip, CS4231P(STATUS));
1188        wss_outb(chip, CS4231P(STATUS), 0);
1189        mb();
1190
1191        if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
1192                goto out;
1193
1194        if (hardware) {
1195                chip->hardware = hardware;
1196                goto out;
1197        }
1198
1199        r = snd_wss_in(chip, CS4231_MISC_INFO);
1200
1201        /* set CS423x MODE 2 */
1202        snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2);
1203        for (i = 0; i < 16; i++) {
1204                if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
1205                        /* we have more than 16 registers: check ID */
1206                        if ((r & 0xf) != 0xa)
1207                                goto out_mode;
1208                        /*
1209                         * on CMI8330, CS4231_VERSION is volume control and
1210                         * can be set to 0
1211                         */
1212                        snd_wss_dout(chip, CS4231_VERSION, 0);
1213                        r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1214                        if (!r)
1215                                chip->hardware = WSS_HW_CMI8330;
1216                        goto out_mode;
1217                }
1218        }
1219        if (r & 0x80)
1220                chip->hardware = WSS_HW_CS4248;
1221        else
1222                chip->hardware = WSS_HW_AD1848;
1223out_mode:
1224        snd_wss_dout(chip, CS4231_MISC_INFO, 0);
1225out:
1226        spin_unlock_irqrestore(&chip->reg_lock, flags);
1227        return err;
1228}
1229
1230static int snd_wss_probe(struct snd_wss *chip)
1231{
1232        unsigned long flags;
1233        int i, id, rev, regnum;
1234        unsigned char *ptr;
1235        unsigned int hw;
1236
1237        id = snd_ad1848_probe(chip);
1238        if (id < 0)
1239                return id;
1240
1241        hw = chip->hardware;
1242        if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1243                for (i = 0; i < 50; i++) {
1244                        mb();
1245                        if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
1246                                msleep(2);
1247                        else {
1248                                spin_lock_irqsave(&chip->reg_lock, flags);
1249                                snd_wss_out(chip, CS4231_MISC_INFO,
1250                                            CS4231_MODE2);
1251                                id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
1252                                spin_unlock_irqrestore(&chip->reg_lock, flags);
1253                                if (id == 0x0a)
1254                                        break;  /* this is valid value */
1255                        }
1256                }
1257                snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
1258                if (id != 0x0a)
1259                        return -ENODEV; /* no valid device found */
1260
1261                rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1262                snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
1263                if (rev == 0x80) {
1264                        unsigned char tmp = snd_wss_in(chip, 23);
1265                        snd_wss_out(chip, 23, ~tmp);
1266                        if (snd_wss_in(chip, 23) != tmp)
1267                                chip->hardware = WSS_HW_AD1845;
1268                        else
1269                                chip->hardware = WSS_HW_CS4231;
1270                } else if (rev == 0xa0) {
1271                        chip->hardware = WSS_HW_CS4231A;
1272                } else if (rev == 0xa2) {
1273                        chip->hardware = WSS_HW_CS4232;
1274                } else if (rev == 0xb2) {
1275                        chip->hardware = WSS_HW_CS4232A;
1276                } else if (rev == 0x83) {
1277                        chip->hardware = WSS_HW_CS4236;
1278                } else if (rev == 0x03) {
1279                        chip->hardware = WSS_HW_CS4236B;
1280                } else {
1281                        snd_printk("unknown CS chip with version 0x%x\n", rev);
1282                        return -ENODEV;         /* unknown CS4231 chip? */
1283                }
1284        }
1285        spin_lock_irqsave(&chip->reg_lock, flags);
1286        wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
1287        wss_outb(chip, CS4231P(STATUS), 0);
1288        mb();
1289        spin_unlock_irqrestore(&chip->reg_lock, flags);
1290
1291        if (!(chip->hardware & WSS_HW_AD1848_MASK))
1292                chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1293        switch (chip->hardware) {
1294        case WSS_HW_INTERWAVE:
1295                chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
1296                break;
1297        case WSS_HW_CS4235:
1298        case WSS_HW_CS4236B:
1299        case WSS_HW_CS4237B:
1300        case WSS_HW_CS4238B:
1301        case WSS_HW_CS4239:
1302                if (hw == WSS_HW_DETECT3)
1303                        chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
1304                else
1305                        chip->hardware = WSS_HW_CS4236;
1306                break;
1307        }
1308
1309        chip->image[CS4231_IFACE_CTRL] =
1310            (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
1311            (chip->single_dma ? CS4231_SINGLE_DMA : 0);
1312        if (chip->hardware != WSS_HW_OPTI93X) {
1313                chip->image[CS4231_ALT_FEATURE_1] = 0x80;
1314                chip->image[CS4231_ALT_FEATURE_2] =
1315                        chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
1316        }
1317        ptr = (unsigned char *) &chip->image;
1318        regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
1319        snd_wss_mce_down(chip);
1320        spin_lock_irqsave(&chip->reg_lock, flags);
1321        for (i = 0; i < regnum; i++)    /* ok.. fill all registers */
1322                snd_wss_out(chip, i, *ptr++);
1323        spin_unlock_irqrestore(&chip->reg_lock, flags);
1324        snd_wss_mce_up(chip);
1325        snd_wss_mce_down(chip);
1326
1327        mdelay(2);
1328
1329        /* ok.. try check hardware version for CS4236+ chips */
1330        if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1331                if (chip->hardware == WSS_HW_CS4236B) {
1332                        rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
1333                        snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
1334                        id = snd_cs4236_ext_in(chip, CS4236_VERSION);
1335                        snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
1336                        snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
1337                        if ((id & 0x1f) == 0x1d) {      /* CS4235 */
1338                                chip->hardware = WSS_HW_CS4235;
1339                                switch (id >> 5) {
1340                                case 4:
1341                                case 5:
1342                                case 6:
1343                                        break;
1344                                default:
1345                                        snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
1346                                }
1347                        } else if ((id & 0x1f) == 0x0b) {       /* CS4236/B */
1348                                switch (id >> 5) {
1349                                case 4:
1350                                case 5:
1351                                case 6:
1352                                case 7:
1353                                        chip->hardware = WSS_HW_CS4236B;
1354                                        break;
1355                                default:
1356                                        snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
1357                                }
1358                        } else if ((id & 0x1f) == 0x08) {       /* CS4237B */
1359                                chip->hardware = WSS_HW_CS4237B;
1360                                switch (id >> 5) {
1361                                case 4:
1362                                case 5:
1363                                case 6:
1364                                case 7:
1365                                        break;
1366                                default:
1367                                        snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
1368                                }
1369                        } else if ((id & 0x1f) == 0x09) {       /* CS4238B */
1370                                chip->hardware = WSS_HW_CS4238B;
1371                                switch (id >> 5) {
1372                                case 5:
1373                                case 6:
1374                                case 7:
1375                                        break;
1376                                default:
1377                                        snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
1378                                }
1379                        } else if ((id & 0x1f) == 0x1e) {       /* CS4239 */
1380                                chip->hardware = WSS_HW_CS4239;
1381                                switch (id >> 5) {
1382                                case 4:
1383                                case 5:
1384                                case 6:
1385                                        break;
1386                                default:
1387                                        snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
1388                                }
1389                        } else {
1390                                snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
1391                        }
1392                }
1393        }
1394        return 0;               /* all things are ok.. */
1395}
1396
1397/*
1398
1399 */
1400
1401static struct snd_pcm_hardware snd_wss_playback =
1402{
1403        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1404                                 SNDRV_PCM_INFO_MMAP_VALID |
1405                                 SNDRV_PCM_INFO_RESUME |
1406                                 SNDRV_PCM_INFO_SYNC_START),
1407        .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1408                                 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1409        .rates =                SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1410        .rate_min =             5510,
1411        .rate_max =             48000,
1412        .channels_min =         1,
1413        .channels_max =         2,
1414        .buffer_bytes_max =     (128*1024),
1415        .period_bytes_min =     64,
1416        .period_bytes_max =     (128*1024),
1417        .periods_min =          1,
1418        .periods_max =          1024,
1419        .fifo_size =            0,
1420};
1421
1422static struct snd_pcm_hardware snd_wss_capture =
1423{
1424        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1425                                 SNDRV_PCM_INFO_MMAP_VALID |
1426                                 SNDRV_PCM_INFO_RESUME |
1427                                 SNDRV_PCM_INFO_SYNC_START),
1428        .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1429                                 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1430        .rates =                SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1431        .rate_min =             5510,
1432        .rate_max =             48000,
1433        .channels_min =         1,
1434        .channels_max =         2,
1435        .buffer_bytes_max =     (128*1024),
1436        .period_bytes_min =     64,
1437        .period_bytes_max =     (128*1024),
1438        .periods_min =          1,
1439        .periods_max =          1024,
1440        .fifo_size =            0,
1441};
1442
1443/*
1444
1445 */
1446
1447static int snd_wss_playback_open(struct snd_pcm_substream *substream)
1448{
1449        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1450        struct snd_pcm_runtime *runtime = substream->runtime;
1451        int err;
1452
1453        runtime->hw = snd_wss_playback;
1454
1455        /* hardware limitation of older chipsets */
1456        if (chip->hardware & WSS_HW_AD1848_MASK)
1457                runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1458                                         SNDRV_PCM_FMTBIT_S16_BE);
1459
1460        /* hardware bug in InterWave chipset */
1461        if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
1462                runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
1463
1464        /* hardware limitation of cheap chips */
1465        if (chip->hardware == WSS_HW_CS4235 ||
1466            chip->hardware == WSS_HW_CS4239)
1467                runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1468
1469        snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1470        snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
1471
1472        if (chip->claim_dma) {
1473                if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1474                        return err;
1475        }
1476
1477        err = snd_wss_open(chip, WSS_MODE_PLAY);
1478        if (err < 0) {
1479                if (chip->release_dma)
1480                        chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1481                snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1482                return err;
1483        }
1484        chip->playback_substream = substream;
1485        snd_pcm_set_sync(substream);
1486        chip->rate_constraint(runtime);
1487        return 0;
1488}
1489
1490static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1491{
1492        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1493        struct snd_pcm_runtime *runtime = substream->runtime;
1494        int err;
1495
1496        runtime->hw = snd_wss_capture;
1497
1498        /* hardware limitation of older chipsets */
1499        if (chip->hardware & WSS_HW_AD1848_MASK)
1500                runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1501                                         SNDRV_PCM_FMTBIT_S16_BE);
1502
1503        /* hardware limitation of cheap chips */
1504        if (chip->hardware == WSS_HW_CS4235 ||
1505            chip->hardware == WSS_HW_CS4239 ||
1506            chip->hardware == WSS_HW_OPTI93X)
1507                runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
1508                                      SNDRV_PCM_FMTBIT_S16_LE;
1509
1510        snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1511        snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1512
1513        if (chip->claim_dma) {
1514                if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1515                        return err;
1516        }
1517
1518        err = snd_wss_open(chip, WSS_MODE_RECORD);
1519        if (err < 0) {
1520                if (chip->release_dma)
1521                        chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1522                snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1523                return err;
1524        }
1525        chip->capture_substream = substream;
1526        snd_pcm_set_sync(substream);
1527        chip->rate_constraint(runtime);
1528        return 0;
1529}
1530
1531static int snd_wss_playback_close(struct snd_pcm_substream *substream)
1532{
1533        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1534
1535        chip->playback_substream = NULL;
1536        snd_wss_close(chip, WSS_MODE_PLAY);
1537        return 0;
1538}
1539
1540static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1541{
1542        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1543
1544        chip->capture_substream = NULL;
1545        snd_wss_close(chip, WSS_MODE_RECORD);
1546        return 0;
1547}
1548
1549static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1550{
1551        int tmp;
1552
1553        if (!chip->thinkpad_flag)
1554                return;
1555
1556        outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1557        tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1558
1559        if (on)
1560                /* turn it on */
1561                tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1562        else
1563                /* turn it off */
1564                tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1565
1566        outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1567}
1568
1569#ifdef CONFIG_PM
1570
1571/* lowlevel suspend callback for CS4231 */
1572static void snd_wss_suspend(struct snd_wss *chip)
1573{
1574        int reg;
1575        unsigned long flags;
1576
1577        snd_pcm_suspend_all(chip->pcm);
1578        spin_lock_irqsave(&chip->reg_lock, flags);
1579        for (reg = 0; reg < 32; reg++)
1580                chip->image[reg] = snd_wss_in(chip, reg);
1581        spin_unlock_irqrestore(&chip->reg_lock, flags);
1582        if (chip->thinkpad_flag)
1583                snd_wss_thinkpad_twiddle(chip, 0);
1584}
1585
1586/* lowlevel resume callback for CS4231 */
1587static void snd_wss_resume(struct snd_wss *chip)
1588{
1589        int reg;
1590        unsigned long flags;
1591        /* int timeout; */
1592
1593        if (chip->thinkpad_flag)
1594                snd_wss_thinkpad_twiddle(chip, 1);
1595        snd_wss_mce_up(chip);
1596        spin_lock_irqsave(&chip->reg_lock, flags);
1597        for (reg = 0; reg < 32; reg++) {
1598                switch (reg) {
1599                case CS4231_VERSION:
1600                        break;
1601                default:
1602                        snd_wss_out(chip, reg, chip->image[reg]);
1603                        break;
1604                }
1605        }
1606        spin_unlock_irqrestore(&chip->reg_lock, flags);
1607#if 1
1608        snd_wss_mce_down(chip);
1609#else
1610        /* The following is a workaround to avoid freeze after resume on TP600E.
1611           This is the first half of copy of snd_wss_mce_down(), but doesn't
1612           include rescheduling.  -- iwai
1613           */
1614        snd_wss_busy_wait(chip);
1615        spin_lock_irqsave(&chip->reg_lock, flags);
1616        chip->mce_bit &= ~CS4231_MCE;
1617        timeout = wss_inb(chip, CS4231P(REGSEL));
1618        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1619        spin_unlock_irqrestore(&chip->reg_lock, flags);
1620        if (timeout == 0x80)
1621                snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
1622        if ((timeout & CS4231_MCE) == 0 ||
1623            !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
1624                return;
1625        }
1626        snd_wss_busy_wait(chip);
1627#endif
1628}
1629#endif /* CONFIG_PM */
1630
1631static int snd_wss_free(struct snd_wss *chip)
1632{
1633        release_and_free_resource(chip->res_port);
1634        release_and_free_resource(chip->res_cport);
1635        if (chip->irq >= 0) {
1636                disable_irq(chip->irq);
1637                if (!(chip->hwshare & WSS_HWSHARE_IRQ))
1638                        free_irq(chip->irq, (void *) chip);
1639        }
1640        if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
1641                snd_dma_disable(chip->dma1);
1642                free_dma(chip->dma1);
1643        }
1644        if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
1645            chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1646                snd_dma_disable(chip->dma2);
1647                free_dma(chip->dma2);
1648        }
1649        if (chip->timer)
1650                snd_device_free(chip->card, chip->timer);
1651        kfree(chip);
1652        return 0;
1653}
1654
1655static int snd_wss_dev_free(struct snd_device *device)
1656{
1657        struct snd_wss *chip = device->device_data;
1658        return snd_wss_free(chip);
1659}
1660
1661const char *snd_wss_chip_id(struct snd_wss *chip)
1662{
1663        switch (chip->hardware) {
1664        case WSS_HW_CS4231:
1665                return "CS4231";
1666        case WSS_HW_CS4231A:
1667                return "CS4231A";
1668        case WSS_HW_CS4232:
1669                return "CS4232";
1670        case WSS_HW_CS4232A:
1671                return "CS4232A";
1672        case WSS_HW_CS4235:
1673                return "CS4235";
1674        case WSS_HW_CS4236:
1675                return "CS4236";
1676        case WSS_HW_CS4236B:
1677                return "CS4236B";
1678        case WSS_HW_CS4237B:
1679                return "CS4237B";
1680        case WSS_HW_CS4238B:
1681                return "CS4238B";
1682        case WSS_HW_CS4239:
1683                return "CS4239";
1684        case WSS_HW_INTERWAVE:
1685                return "AMD InterWave";
1686        case WSS_HW_OPL3SA2:
1687                return chip->card->shortname;
1688        case WSS_HW_AD1845:
1689                return "AD1845";
1690        case WSS_HW_OPTI93X:
1691                return "OPTi 93x";
1692        case WSS_HW_AD1847:
1693                return "AD1847";
1694        case WSS_HW_AD1848:
1695                return "AD1848";
1696        case WSS_HW_CS4248:
1697                return "CS4248";
1698        case WSS_HW_CMI8330:
1699                return "CMI8330/C3D";
1700        default:
1701                return "???";
1702        }
1703}
1704EXPORT_SYMBOL(snd_wss_chip_id);
1705
1706static int snd_wss_new(struct snd_card *card,
1707                          unsigned short hardware,
1708                          unsigned short hwshare,
1709                          struct snd_wss **rchip)
1710{
1711        struct snd_wss *chip;
1712
1713        *rchip = NULL;
1714        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1715        if (chip == NULL)
1716                return -ENOMEM;
1717        chip->hardware = hardware;
1718        chip->hwshare = hwshare;
1719
1720        spin_lock_init(&chip->reg_lock);
1721        mutex_init(&chip->mce_mutex);
1722        mutex_init(&chip->open_mutex);
1723        chip->card = card;
1724        chip->rate_constraint = snd_wss_xrate;
1725        chip->set_playback_format = snd_wss_playback_format;
1726        chip->set_capture_format = snd_wss_capture_format;
1727        if (chip->hardware == WSS_HW_OPTI93X)
1728                memcpy(&chip->image, &snd_opti93x_original_image,
1729                       sizeof(snd_opti93x_original_image));
1730        else
1731                memcpy(&chip->image, &snd_wss_original_image,
1732                       sizeof(snd_wss_original_image));
1733        if (chip->hardware & WSS_HW_AD1848_MASK) {
1734                chip->image[CS4231_PIN_CTRL] = 0;
1735                chip->image[CS4231_TEST_INIT] = 0;
1736        }
1737
1738        *rchip = chip;
1739        return 0;
1740}
1741
1742int snd_wss_create(struct snd_card *card,
1743                      unsigned long port,
1744                      unsigned long cport,
1745                      int irq, int dma1, int dma2,
1746                      unsigned short hardware,
1747                      unsigned short hwshare,
1748                      struct snd_wss **rchip)
1749{
1750        static struct snd_device_ops ops = {
1751                .dev_free =     snd_wss_dev_free,
1752        };
1753        struct snd_wss *chip;
1754        int err;
1755
1756        err = snd_wss_new(card, hardware, hwshare, &chip);
1757        if (err < 0)
1758                return err;
1759
1760        chip->irq = -1;
1761        chip->dma1 = -1;
1762        chip->dma2 = -1;
1763
1764        chip->res_port = request_region(port, 4, "WSS");
1765        if (!chip->res_port) {
1766                snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
1767                snd_wss_free(chip);
1768                return -EBUSY;
1769        }
1770        chip->port = port;
1771        if ((long)cport >= 0) {
1772                chip->res_cport = request_region(cport, 8, "CS4232 Control");
1773                if (!chip->res_cport) {
1774                        snd_printk(KERN_ERR
1775                                "wss: can't grab control port 0x%lx\n", cport);
1776                        snd_wss_free(chip);
1777                        return -ENODEV;
1778                }
1779        }
1780        chip->cport = cport;
1781        if (!(hwshare & WSS_HWSHARE_IRQ))
1782                if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
1783                                "WSS", (void *) chip)) {
1784                        snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
1785                        snd_wss_free(chip);
1786                        return -EBUSY;
1787                }
1788        chip->irq = irq;
1789        if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
1790                snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
1791                snd_wss_free(chip);
1792                return -EBUSY;
1793        }
1794        chip->dma1 = dma1;
1795        if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
1796              dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
1797                snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
1798                snd_wss_free(chip);
1799                return -EBUSY;
1800        }
1801        if (dma1 == dma2 || dma2 < 0) {
1802                chip->single_dma = 1;
1803                chip->dma2 = chip->dma1;
1804        } else
1805                chip->dma2 = dma2;
1806
1807        if (hardware == WSS_HW_THINKPAD) {
1808                chip->thinkpad_flag = 1;
1809                chip->hardware = WSS_HW_DETECT; /* reset */
1810                snd_wss_thinkpad_twiddle(chip, 1);
1811        }
1812
1813        /* global setup */
1814        if (snd_wss_probe(chip) < 0) {
1815                snd_wss_free(chip);
1816                return -ENODEV;
1817        }
1818        snd_wss_init(chip);
1819
1820#if 0
1821        if (chip->hardware & WSS_HW_CS4232_MASK) {
1822                if (chip->res_cport == NULL)
1823                        snd_printk("CS4232 control port features are not accessible\n");
1824        }
1825#endif
1826
1827        /* Register device */
1828        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1829        if (err < 0) {
1830                snd_wss_free(chip);
1831                return err;
1832        }
1833
1834#ifdef CONFIG_PM
1835        /* Power Management */
1836        chip->suspend = snd_wss_suspend;
1837        chip->resume = snd_wss_resume;
1838#endif
1839
1840        *rchip = chip;
1841        return 0;
1842}
1843EXPORT_SYMBOL(snd_wss_create);
1844
1845static struct snd_pcm_ops snd_wss_playback_ops = {
1846        .open =         snd_wss_playback_open,
1847        .close =        snd_wss_playback_close,
1848        .ioctl =        snd_pcm_lib_ioctl,
1849        .hw_params =    snd_wss_playback_hw_params,
1850        .hw_free =      snd_wss_playback_hw_free,
1851        .prepare =      snd_wss_playback_prepare,
1852        .trigger =      snd_wss_trigger,
1853        .pointer =      snd_wss_playback_pointer,
1854};
1855
1856static struct snd_pcm_ops snd_wss_capture_ops = {
1857        .open =         snd_wss_capture_open,
1858        .close =        snd_wss_capture_close,
1859        .ioctl =        snd_pcm_lib_ioctl,
1860        .hw_params =    snd_wss_capture_hw_params,
1861        .hw_free =      snd_wss_capture_hw_free,
1862        .prepare =      snd_wss_capture_prepare,
1863        .trigger =      snd_wss_trigger,
1864        .pointer =      snd_wss_capture_pointer,
1865};
1866
1867int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1868{
1869        struct snd_pcm *pcm;
1870        int err;
1871
1872        err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1873        if (err < 0)
1874                return err;
1875
1876        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1877        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1878
1879        /* global setup */
1880        pcm->private_data = chip;
1881        pcm->info_flags = 0;
1882        if (chip->single_dma)
1883                pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1884        if (chip->hardware != WSS_HW_INTERWAVE)
1885                pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1886        strcpy(pcm->name, snd_wss_chip_id(chip));
1887
1888        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1889                                              snd_dma_isa_data(),
1890                                              64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1891
1892        chip->pcm = pcm;
1893        if (rpcm)
1894                *rpcm = pcm;
1895        return 0;
1896}
1897EXPORT_SYMBOL(snd_wss_pcm);
1898
1899static void snd_wss_timer_free(struct snd_timer *timer)
1900{
1901        struct snd_wss *chip = timer->private_data;
1902        chip->timer = NULL;
1903}
1904
1905int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer)
1906{
1907        struct snd_timer *timer;
1908        struct snd_timer_id tid;
1909        int err;
1910
1911        /* Timer initialization */
1912        tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1913        tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1914        tid.card = chip->card->number;
1915        tid.device = device;
1916        tid.subdevice = 0;
1917        if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1918                return err;
1919        strcpy(timer->name, snd_wss_chip_id(chip));
1920        timer->private_data = chip;
1921        timer->private_free = snd_wss_timer_free;
1922        timer->hw = snd_wss_timer_table;
1923        chip->timer = timer;
1924        if (rtimer)
1925                *rtimer = timer;
1926        return 0;
1927}
1928EXPORT_SYMBOL(snd_wss_timer);
1929
1930/*
1931 *  MIXER part
1932 */
1933
1934static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
1935                            struct snd_ctl_elem_info *uinfo)
1936{
1937        static char *texts[4] = {
1938                "Line", "Aux", "Mic", "Mix"
1939        };
1940        static char *opl3sa_texts[4] = {
1941                "Line", "CD", "Mic", "Mix"
1942        };
1943        static char *gusmax_texts[4] = {
1944                "Line", "Synth", "Mic", "Mix"
1945        };
1946        char **ptexts = texts;
1947        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1948
1949        if (snd_BUG_ON(!chip->card))
1950                return -EINVAL;
1951        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1952        uinfo->count = 2;
1953        uinfo->value.enumerated.items = 4;
1954        if (uinfo->value.enumerated.item > 3)
1955                uinfo->value.enumerated.item = 3;
1956        if (!strcmp(chip->card->driver, "GUS MAX"))
1957                ptexts = gusmax_texts;
1958        switch (chip->hardware) {
1959        case WSS_HW_INTERWAVE:
1960                ptexts = gusmax_texts;
1961                break;
1962        case WSS_HW_OPL3SA2:
1963                ptexts = opl3sa_texts;
1964                break;
1965        }
1966        strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
1967        return 0;
1968}
1969
1970static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
1971                           struct snd_ctl_elem_value *ucontrol)
1972{
1973        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1974        unsigned long flags;
1975
1976        spin_lock_irqsave(&chip->reg_lock, flags);
1977        ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
1978        ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
1979        spin_unlock_irqrestore(&chip->reg_lock, flags);
1980        return 0;
1981}
1982
1983static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
1984                           struct snd_ctl_elem_value *ucontrol)
1985{
1986        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1987        unsigned long flags;
1988        unsigned short left, right;
1989        int change;
1990
1991        if (ucontrol->value.enumerated.item[0] > 3 ||
1992            ucontrol->value.enumerated.item[1] > 3)
1993                return -EINVAL;
1994        left = ucontrol->value.enumerated.item[0] << 6;
1995        right = ucontrol->value.enumerated.item[1] << 6;
1996        spin_lock_irqsave(&chip->reg_lock, flags);
1997        left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
1998        right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
1999        change = left != chip->image[CS4231_LEFT_INPUT] ||
2000                 right != chip->image[CS4231_RIGHT_INPUT];
2001        snd_wss_out(chip, CS4231_LEFT_INPUT, left);
2002        snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
2003        spin_unlock_irqrestore(&chip->reg_lock, flags);
2004        return change;
2005}
2006
2007int snd_wss_info_single(struct snd_kcontrol *kcontrol,
2008                        struct snd_ctl_elem_info *uinfo)
2009{
2010        int mask = (kcontrol->private_value >> 16) & 0xff;
2011
2012        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2013        uinfo->count = 1;
2014        uinfo->value.integer.min = 0;
2015        uinfo->value.integer.max = mask;
2016        return 0;
2017}
2018EXPORT_SYMBOL(snd_wss_info_single);
2019
2020int snd_wss_get_single(struct snd_kcontrol *kcontrol,
2021                       struct snd_ctl_elem_value *ucontrol)
2022{
2023        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2024        unsigned long flags;
2025        int reg = kcontrol->private_value & 0xff;
2026        int shift = (kcontrol->private_value >> 8) & 0xff;
2027        int mask = (kcontrol->private_value >> 16) & 0xff;
2028        int invert = (kcontrol->private_value >> 24) & 0xff;
2029
2030        spin_lock_irqsave(&chip->reg_lock, flags);
2031        ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
2032        spin_unlock_irqrestore(&chip->reg_lock, flags);
2033        if (invert)
2034                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2035        return 0;
2036}
2037EXPORT_SYMBOL(snd_wss_get_single);
2038
2039int snd_wss_put_single(struct snd_kcontrol *kcontrol,
2040                       struct snd_ctl_elem_value *ucontrol)
2041{
2042        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2043        unsigned long flags;
2044        int reg = kcontrol->private_value & 0xff;
2045        int shift = (kcontrol->private_value >> 8) & 0xff;
2046        int mask = (kcontrol->private_value >> 16) & 0xff;
2047        int invert = (kcontrol->private_value >> 24) & 0xff;
2048        int change;
2049        unsigned short val;
2050
2051        val = (ucontrol->value.integer.value[0] & mask);
2052        if (invert)
2053                val = mask - val;
2054        val <<= shift;
2055        spin_lock_irqsave(&chip->reg_lock, flags);
2056        val = (chip->image[reg] & ~(mask << shift)) | val;
2057        change = val != chip->image[reg];
2058        snd_wss_out(chip, reg, val);
2059        spin_unlock_irqrestore(&chip->reg_lock, flags);
2060        return change;
2061}
2062EXPORT_SYMBOL(snd_wss_put_single);
2063
2064int snd_wss_info_double(struct snd_kcontrol *kcontrol,
2065                        struct snd_ctl_elem_info *uinfo)
2066{
2067        int mask = (kcontrol->private_value >> 24) & 0xff;
2068
2069        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2070        uinfo->count = 2;
2071        uinfo->value.integer.min = 0;
2072        uinfo->value.integer.max = mask;
2073        return 0;
2074}
2075EXPORT_SYMBOL(snd_wss_info_double);
2076
2077int snd_wss_get_double(struct snd_kcontrol *kcontrol,
2078                       struct snd_ctl_elem_value *ucontrol)
2079{
2080        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2081        unsigned long flags;
2082        int left_reg = kcontrol->private_value & 0xff;
2083        int right_reg = (kcontrol->private_value >> 8) & 0xff;
2084        int shift_left = (kcontrol->private_value >> 16) & 0x07;
2085        int shift_right = (kcontrol->private_value >> 19) & 0x07;
2086        int mask = (kcontrol->private_value >> 24) & 0xff;
2087        int invert = (kcontrol->private_value >> 22) & 1;
2088
2089        spin_lock_irqsave(&chip->reg_lock, flags);
2090        ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
2091        ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
2092        spin_unlock_irqrestore(&chip->reg_lock, flags);
2093        if (invert) {
2094                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2095                ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
2096        }
2097        return 0;
2098}
2099EXPORT_SYMBOL(snd_wss_get_double);
2100
2101int snd_wss_put_double(struct snd_kcontrol *kcontrol,
2102                       struct snd_ctl_elem_value *ucontrol)
2103{
2104        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2105        unsigned long flags;
2106        int left_reg = kcontrol->private_value & 0xff;
2107        int right_reg = (kcontrol->private_value >> 8) & 0xff;
2108        int shift_left = (kcontrol->private_value >> 16) & 0x07;
2109        int shift_right = (kcontrol->private_value >> 19) & 0x07;
2110        int mask = (kcontrol->private_value >> 24) & 0xff;
2111        int invert = (kcontrol->private_value >> 22) & 1;
2112        int change;
2113        unsigned short val1, val2;
2114
2115        val1 = ucontrol->value.integer.value[0] & mask;
2116        val2 = ucontrol->value.integer.value[1] & mask;
2117        if (invert) {
2118                val1 = mask - val1;
2119                val2 = mask - val2;
2120        }
2121        val1 <<= shift_left;
2122        val2 <<= shift_right;
2123        spin_lock_irqsave(&chip->reg_lock, flags);
2124        if (left_reg != right_reg) {
2125                val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
2126                val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
2127                change = val1 != chip->image[left_reg] ||
2128                         val2 != chip->image[right_reg];
2129                snd_wss_out(chip, left_reg, val1);
2130                snd_wss_out(chip, right_reg, val2);
2131        } else {
2132                mask = (mask << shift_left) | (mask << shift_right);
2133                val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
2134                change = val1 != chip->image[left_reg];
2135                snd_wss_out(chip, left_reg, val1);
2136        }
2137        spin_unlock_irqrestore(&chip->reg_lock, flags);
2138        return change;
2139}
2140EXPORT_SYMBOL(snd_wss_put_double);
2141
2142static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
2143static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
2144static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
2145
2146static struct snd_kcontrol_new snd_ad1848_controls[] = {
2147WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT,
2148           7, 7, 1, 1),
2149WSS_DOUBLE_TLV("PCM Playback Volume", 0,
2150               CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
2151               db_scale_6bit),
2152WSS_DOUBLE("Aux Playback Switch", 0,
2153           CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2154WSS_DOUBLE_TLV("Aux Playback Volume", 0,
2155               CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
2156               db_scale_5bit_12db_max),
2157WSS_DOUBLE("Aux Playback Switch", 1,
2158           CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2159WSS_DOUBLE_TLV("Aux Playback Volume", 1,
2160               CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
2161               db_scale_5bit_12db_max),
2162WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
2163                0, 0, 15, 0, db_scale_rec_gain),
2164{
2165        .name = "Capture Source",
2166        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2167        .info = snd_wss_info_mux,
2168        .get = snd_wss_get_mux,
2169        .put = snd_wss_put_mux,
2170},
2171WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
2172WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0,
2173               db_scale_6bit),
2174};
2175
2176static struct snd_kcontrol_new snd_wss_controls[] = {
2177WSS_DOUBLE("PCM Playback Switch", 0,
2178                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2179WSS_DOUBLE("PCM Playback Volume", 0,
2180                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
2181WSS_DOUBLE("Line Playback Switch", 0,
2182                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2183WSS_DOUBLE("Line Playback Volume", 0,
2184                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
2185WSS_DOUBLE("Aux Playback Switch", 0,
2186                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2187WSS_DOUBLE("Aux Playback Volume", 0,
2188                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
2189WSS_DOUBLE("Aux Playback Switch", 1,
2190                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2191WSS_DOUBLE("Aux Playback Volume", 1,
2192                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
2193WSS_SINGLE("Mono Playback Switch", 0,
2194                CS4231_MONO_CTRL, 7, 1, 1),
2195WSS_SINGLE("Mono Playback Volume", 0,
2196                CS4231_MONO_CTRL, 0, 15, 1),
2197WSS_SINGLE("Mono Output Playback Switch", 0,
2198                CS4231_MONO_CTRL, 6, 1, 1),
2199WSS_SINGLE("Mono Output Playback Bypass", 0,
2200                CS4231_MONO_CTRL, 5, 1, 0),
2201WSS_DOUBLE("Capture Volume", 0,
2202                CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2203{
2204        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2205        .name = "Capture Source",
2206        .info = snd_wss_info_mux,
2207        .get = snd_wss_get_mux,
2208        .put = snd_wss_put_mux,
2209},
2210WSS_DOUBLE("Mic Boost", 0,
2211                CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2212WSS_SINGLE("Loopback Capture Switch", 0,
2213                CS4231_LOOPBACK, 0, 1, 0),
2214WSS_SINGLE("Loopback Capture Volume", 0,
2215                CS4231_LOOPBACK, 2, 63, 1)
2216};
2217
2218static struct snd_kcontrol_new snd_opti93x_controls[] = {
2219WSS_DOUBLE("Master Playback Switch", 0,
2220                OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
2221WSS_DOUBLE("Master Playback Volume", 0,
2222                OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
2223WSS_DOUBLE("PCM Playback Switch", 0,
2224                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2225WSS_DOUBLE("PCM Playback Volume", 0,
2226                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
2227WSS_DOUBLE("FM Playback Switch", 0,
2228                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2229WSS_DOUBLE("FM Playback Volume", 0,
2230                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
2231WSS_DOUBLE("Line Playback Switch", 0,
2232                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2233WSS_DOUBLE("Line Playback Volume", 0,
2234                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
2235WSS_DOUBLE("Mic Playback Switch", 0,
2236                OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
2237WSS_DOUBLE("Mic Playback Volume", 0,
2238                OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
2239WSS_DOUBLE("Mic Boost", 0,
2240                CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2241WSS_DOUBLE("CD Playback Switch", 0,
2242                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2243WSS_DOUBLE("CD Playback Volume", 0,
2244                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
2245WSS_DOUBLE("Aux Playback Switch", 0,
2246                OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
2247WSS_DOUBLE("Aux Playback Volume", 0,
2248                OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
2249WSS_DOUBLE("Capture Volume", 0,
2250                CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2251{
2252        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2253        .name = "Capture Source",
2254        .info = snd_wss_info_mux,
2255        .get = snd_wss_get_mux,
2256        .put = snd_wss_put_mux,
2257}
2258};
2259
2260int snd_wss_mixer(struct snd_wss *chip)
2261{
2262        struct snd_card *card;
2263        unsigned int idx;
2264        int err;
2265
2266        if (snd_BUG_ON(!chip || !chip->pcm))
2267                return -EINVAL;
2268
2269        card = chip->card;
2270
2271        strcpy(card->mixername, chip->pcm->name);
2272
2273        if (chip->hardware == WSS_HW_OPTI93X)
2274                for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
2275                        err = snd_ctl_add(card,
2276                                        snd_ctl_new1(&snd_opti93x_controls[idx],
2277                                                     chip));
2278                        if (err < 0)
2279                                return err;
2280                }
2281        else if (chip->hardware & WSS_HW_AD1848_MASK)
2282                for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) {
2283                        err = snd_ctl_add(card,
2284                                        snd_ctl_new1(&snd_ad1848_controls[idx],
2285                                                     chip));
2286                        if (err < 0)
2287                                return err;
2288                }
2289        else
2290                for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) {
2291                        err = snd_ctl_add(card,
2292                                        snd_ctl_new1(&snd_wss_controls[idx],
2293                                                     chip));
2294                        if (err < 0)
2295                                return err;
2296                }
2297        return 0;
2298}
2299EXPORT_SYMBOL(snd_wss_mixer);
2300
2301const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2302{
2303        return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2304                &snd_wss_playback_ops : &snd_wss_capture_ops;
2305}
2306EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2307
2308/*
2309 *  INIT part
2310 */
2311
2312static int __init alsa_wss_init(void)
2313{
2314        return 0;
2315}
2316
2317static void __exit alsa_wss_exit(void)
2318{
2319}
2320
2321module_init(alsa_wss_init);
2322module_exit(alsa_wss_exit);
2323
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.