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