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 <linux/io.h>
  35#include <sound/core.h>
  36#include <sound/wss.h>
  37#include <sound/pcm_params.h>
  38#include <sound/tlv.h>
  39
  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_SYNC_START),
1460        .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1461                                 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1462        .rates =                SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1463        .rate_min =             5510,
1464        .rate_max =             48000,
1465        .channels_min =         1,
1466        .channels_max =         2,
1467        .buffer_bytes_max =     (128*1024),
1468        .period_bytes_min =     64,
1469        .period_bytes_max =     (128*1024),
1470        .periods_min =          1,
1471        .periods_max =          1024,
1472        .fifo_size =            0,
1473};
1474
1475static struct snd_pcm_hardware snd_wss_capture =
1476{
1477        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1478                                 SNDRV_PCM_INFO_MMAP_VALID |
1479                                 SNDRV_PCM_INFO_RESUME |
1480                                 SNDRV_PCM_INFO_SYNC_START),
1481        .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1482                                 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1483        .rates =                SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1484        .rate_min =             5510,
1485        .rate_max =             48000,
1486        .channels_min =         1,
1487        .channels_max =         2,
1488        .buffer_bytes_max =     (128*1024),
1489        .period_bytes_min =     64,
1490        .period_bytes_max =     (128*1024),
1491        .periods_min =          1,
1492        .periods_max =          1024,
1493        .fifo_size =            0,
1494};
1495
1496/*
1497
1498 */
1499
1500static int snd_wss_playback_open(struct snd_pcm_substream *substream)
1501{
1502        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1503        struct snd_pcm_runtime *runtime = substream->runtime;
1504        int err;
1505
1506        runtime->hw = snd_wss_playback;
1507
1508        /* hardware limitation of older chipsets */
1509        if (chip->hardware & WSS_HW_AD1848_MASK)
1510                runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1511                                         SNDRV_PCM_FMTBIT_S16_BE);
1512
1513        /* hardware bug in InterWave chipset */
1514        if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
1515                runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
1516
1517        /* hardware limitation of cheap chips */
1518        if (chip->hardware == WSS_HW_CS4235 ||
1519            chip->hardware == WSS_HW_CS4239)
1520                runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1521
1522        snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1523        snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
1524
1525        if (chip->claim_dma) {
1526                if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1527                        return err;
1528        }
1529
1530        err = snd_wss_open(chip, WSS_MODE_PLAY);
1531        if (err < 0) {
1532                if (chip->release_dma)
1533                        chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1534                snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1535                return err;
1536        }
1537        chip->playback_substream = substream;
1538        snd_pcm_set_sync(substream);
1539        chip->rate_constraint(runtime);
1540        return 0;
1541}
1542
1543static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1544{
1545        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1546        struct snd_pcm_runtime *runtime = substream->runtime;
1547        int err;
1548
1549        runtime->hw = snd_wss_capture;
1550
1551        /* hardware limitation of older chipsets */
1552        if (chip->hardware & WSS_HW_AD1848_MASK)
1553                runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1554                                         SNDRV_PCM_FMTBIT_S16_BE);
1555
1556        /* hardware limitation of cheap chips */
1557        if (chip->hardware == WSS_HW_CS4235 ||
1558            chip->hardware == WSS_HW_CS4239 ||
1559            chip->hardware == WSS_HW_OPTI93X)
1560                runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
1561                                      SNDRV_PCM_FMTBIT_S16_LE;
1562
1563        snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1564        snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1565
1566        if (chip->claim_dma) {
1567                if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1568                        return err;
1569        }
1570
1571        err = snd_wss_open(chip, WSS_MODE_RECORD);
1572        if (err < 0) {
1573                if (chip->release_dma)
1574                        chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1575                snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1576                return err;
1577        }
1578        chip->capture_substream = substream;
1579        snd_pcm_set_sync(substream);
1580        chip->rate_constraint(runtime);
1581        return 0;
1582}
1583
1584static int snd_wss_playback_close(struct snd_pcm_substream *substream)
1585{
1586        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1587
1588        chip->playback_substream = NULL;
1589        snd_wss_close(chip, WSS_MODE_PLAY);
1590        return 0;
1591}
1592
1593static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1594{
1595        struct snd_wss *chip = snd_pcm_substream_chip(substream);
1596
1597        chip->capture_substream = NULL;
1598        snd_wss_close(chip, WSS_MODE_RECORD);
1599        return 0;
1600}
1601
1602static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1603{
1604        int tmp;
1605
1606        if (!chip->thinkpad_flag)
1607                return;
1608
1609        outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1610        tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1611
1612        if (on)
1613                /* turn it on */
1614                tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1615        else
1616                /* turn it off */
1617                tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1618
1619        outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1620}
1621
1622#ifdef CONFIG_PM
1623
1624/* lowlevel suspend callback for CS4231 */
1625static void snd_wss_suspend(struct snd_wss *chip)
1626{
1627        int reg;
1628        unsigned long flags;
1629
1630        snd_pcm_suspend_all(chip->pcm);
1631        spin_lock_irqsave(&chip->reg_lock, flags);
1632        for (reg = 0; reg < 32; reg++)
1633                chip->image[reg] = snd_wss_in(chip, reg);
1634        spin_unlock_irqrestore(&chip->reg_lock, flags);
1635        if (chip->thinkpad_flag)
1636                snd_wss_thinkpad_twiddle(chip, 0);
1637}
1638
1639/* lowlevel resume callback for CS4231 */
1640static void snd_wss_resume(struct snd_wss *chip)
1641{
1642        int reg;
1643        unsigned long flags;
1644        /* int timeout; */
1645
1646        if (chip->thinkpad_flag)
1647                snd_wss_thinkpad_twiddle(chip, 1);
1648        snd_wss_mce_up(chip);
1649        spin_lock_irqsave(&chip->reg_lock, flags);
1650        for (reg = 0; reg < 32; reg++) {
1651                switch (reg) {
1652                case CS4231_VERSION:
1653                        break;
1654                default:
1655                        snd_wss_out(chip, reg, chip->image[reg]);
1656                        break;
1657                }
1658        }
1659        /* Yamaha needs this to resume properly */
1660        if (chip->hardware == WSS_HW_OPL3SA2)
1661                snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
1662                            chip->image[CS4231_PLAYBK_FORMAT]);
1663        spin_unlock_irqrestore(&chip->reg_lock, flags);
1664#if 1
1665        snd_wss_mce_down(chip);
1666#else
1667        /* The following is a workaround to avoid freeze after resume on TP600E.
1668           This is the first half of copy of snd_wss_mce_down(), but doesn't
1669           include rescheduling.  -- iwai
1670           */
1671        snd_wss_busy_wait(chip);
1672        spin_lock_irqsave(&chip->reg_lock, flags);
1673        chip->mce_bit &= ~CS4231_MCE;
1674        timeout = wss_inb(chip, CS4231P(REGSEL));
1675        wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1676        spin_unlock_irqrestore(&chip->reg_lock, flags);
1677        if (timeout == 0x80)
1678                snd_printk(KERN_ERR "down [0x%lx]: serious init problem "
1679                           "- codec still busy\n", chip->port);
1680        if ((timeout & CS4231_MCE) == 0 ||
1681            !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
1682                return;
1683        }
1684        snd_wss_busy_wait(chip);
1685#endif
1686}
1687#endif /* CONFIG_PM */
1688
1689static int snd_wss_free(struct snd_wss *chip)
1690{
1691        release_and_free_resource(chip->res_port);
1692        release_and_free_resource(chip->res_cport);
1693        if (chip->irq >= 0) {
1694                disable_irq(chip->irq);
1695                if (!(chip->hwshare & WSS_HWSHARE_IRQ))
1696                        free_irq(chip->irq, (void *) chip);
1697        }
1698        if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
1699                snd_dma_disable(chip->dma1);
1700                free_dma(chip->dma1);
1701        }
1702        if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
1703            chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1704                snd_dma_disable(chip->dma2);
1705                free_dma(chip->dma2);
1706        }
1707        if (chip->timer)
1708                snd_device_free(chip->card, chip->timer);
1709        kfree(chip);
1710        return 0;
1711}
1712
1713static int snd_wss_dev_free(struct snd_device *device)
1714{
1715        struct snd_wss *chip = device->device_data;
1716        return snd_wss_free(chip);
1717}
1718
1719const char *snd_wss_chip_id(struct snd_wss *chip)
1720{
1721        switch (chip->hardware) {
1722        case WSS_HW_CS4231:
1723                return "CS4231";
1724        case WSS_HW_CS4231A:
1725                return "CS4231A";
1726        case WSS_HW_CS4232:
1727                return "CS4232";
1728        case WSS_HW_CS4232A:
1729                return "CS4232A";
1730        case WSS_HW_CS4235:
1731                return "CS4235";
1732        case WSS_HW_CS4236:
1733                return "CS4236";
1734        case WSS_HW_CS4236B:
1735                return "CS4236B";
1736        case WSS_HW_CS4237B:
1737                return "CS4237B";
1738        case WSS_HW_CS4238B:
1739                return "CS4238B";
1740        case WSS_HW_CS4239:
1741                return "CS4239";
1742        case WSS_HW_INTERWAVE:
1743                return "AMD InterWave";
1744        case WSS_HW_OPL3SA2:
1745                return chip->card->shortname;
1746        case WSS_HW_AD1845:
1747                return "AD1845";
1748        case WSS_HW_OPTI93X:
1749                return "OPTi 93x";
1750        case WSS_HW_AD1847:
1751                return "AD1847";
1752        case WSS_HW_AD1848:
1753                return "AD1848";
1754        case WSS_HW_CS4248:
1755                return "CS4248";
1756        case WSS_HW_CMI8330:
1757                return "CMI8330/C3D";
1758        default:
1759                return "???";
1760        }
1761}
1762EXPORT_SYMBOL(snd_wss_chip_id);
1763
1764static int snd_wss_new(struct snd_card *card,
1765                          unsigned short hardware,
1766                          unsigned short hwshare,
1767                          struct snd_wss **rchip)
1768{
1769        struct snd_wss *chip;
1770
1771        *rchip = NULL;
1772        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1773        if (chip == NULL)
1774                return -ENOMEM;
1775        chip->hardware = hardware;
1776        chip->hwshare = hwshare;
1777
1778        spin_lock_init(&chip->reg_lock);
1779        mutex_init(&chip->mce_mutex);
1780        mutex_init(&chip->open_mutex);
1781        chip->card = card;
1782        chip->rate_constraint = snd_wss_xrate;
1783        chip->set_playback_format = snd_wss_playback_format;
1784        chip->set_capture_format = snd_wss_capture_format;
1785        if (chip->hardware == WSS_HW_OPTI93X)
1786                memcpy(&chip->image, &snd_opti93x_original_image,
1787                       sizeof(snd_opti93x_original_image));
1788        else
1789                memcpy(&chip->image, &snd_wss_original_image,
1790                       sizeof(snd_wss_original_image));
1791        if (chip->hardware & WSS_HW_AD1848_MASK) {
1792                chip->image[CS4231_PIN_CTRL] = 0;
1793                chip->image[CS4231_TEST_INIT] = 0;
1794        }
1795
1796        *rchip = chip;
1797        return 0;
1798}
1799
1800int snd_wss_create(struct snd_card *card,
1801                      unsigned long port,
1802                      unsigned long cport,
1803                      int irq, int dma1, int dma2,
1804                      unsigned short hardware,
1805                      unsigned short hwshare,
1806                      struct snd_wss **rchip)
1807{
1808        static struct snd_device_ops ops = {
1809                .dev_free =     snd_wss_dev_free,
1810        };
1811        struct snd_wss *chip;
1812        int err;
1813
1814        err = snd_wss_new(card, hardware, hwshare, &chip);
1815        if (err < 0)
1816                return err;
1817
1818        chip->irq = -1;
1819        chip->dma1 = -1;
1820        chip->dma2 = -1;
1821
1822        chip->res_port = request_region(port, 4, "WSS");
1823        if (!chip->res_port) {
1824                snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
1825                snd_wss_free(chip);
1826                return -EBUSY;
1827        }
1828        chip->port = port;
1829        if ((long)cport >= 0) {
1830                chip->res_cport = request_region(cport, 8, "CS4232 Control");
1831                if (!chip->res_cport) {
1832                        snd_printk(KERN_ERR
1833                                "wss: can't grab control port 0x%lx\n", cport);
1834                        snd_wss_free(chip);
1835                        return -ENODEV;
1836                }
1837        }
1838        chip->cport = cport;
1839        if (!(hwshare & WSS_HWSHARE_IRQ))
1840                if (request_irq(irq, snd_wss_interrupt, 0,
1841                                "WSS", (void *) chip)) {
1842                        snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
1843                        snd_wss_free(chip);
1844                        return -EBUSY;
1845                }
1846        chip->irq = irq;
1847        if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
1848                snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
1849                snd_wss_free(chip);
1850                return -EBUSY;
1851        }
1852        chip->dma1 = dma1;
1853        if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
1854              dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
1855                snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
1856                snd_wss_free(chip);
1857                return -EBUSY;
1858        }
1859        if (dma1 == dma2 || dma2 < 0) {
1860                chip->single_dma = 1;
1861                chip->dma2 = chip->dma1;
1862        } else
1863                chip->dma2 = dma2;
1864
1865        if (hardware == WSS_HW_THINKPAD) {
1866                chip->thinkpad_flag = 1;
1867                chip->hardware = WSS_HW_DETECT; /* reset */
1868                snd_wss_thinkpad_twiddle(chip, 1);
1869        }
1870
1871        /* global setup */
1872        if (snd_wss_probe(chip) < 0) {
1873                snd_wss_free(chip);
1874                return -ENODEV;
1875        }
1876        snd_wss_init(chip);
1877
1878#if 0
1879        if (chip->hardware & WSS_HW_CS4232_MASK) {
1880                if (chip->res_cport == NULL)
1881                        snd_printk(KERN_ERR "CS4232 control port features are "
1882                                   "not accessible\n");
1883        }
1884#endif
1885
1886        /* Register device */
1887        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1888        if (err < 0) {
1889                snd_wss_free(chip);
1890                return err;
1891        }
1892
1893#ifdef CONFIG_PM
1894        /* Power Management */
1895        chip->suspend = snd_wss_suspend;
1896        chip->resume = snd_wss_resume;
1897#endif
1898
1899        *rchip = chip;
1900        return 0;
1901}
1902EXPORT_SYMBOL(snd_wss_create);
1903
1904static struct snd_pcm_ops snd_wss_playback_ops = {
1905        .open =         snd_wss_playback_open,
1906        .close =        snd_wss_playback_close,
1907        .ioctl =        snd_pcm_lib_ioctl,
1908        .hw_params =    snd_wss_playback_hw_params,
1909        .hw_free =      snd_wss_playback_hw_free,
1910        .prepare =      snd_wss_playback_prepare,
1911        .trigger =      snd_wss_trigger,
1912        .pointer =      snd_wss_playback_pointer,
1913};
1914
1915static struct snd_pcm_ops snd_wss_capture_ops = {
1916        .open =         snd_wss_capture_open,
1917        .close =        snd_wss_capture_close,
1918        .ioctl =        snd_pcm_lib_ioctl,
1919        .hw_params =    snd_wss_capture_hw_params,
1920        .hw_free =      snd_wss_capture_hw_free,
1921        .prepare =      snd_wss_capture_prepare,
1922        .trigger =      snd_wss_trigger,
1923        .pointer =      snd_wss_capture_pointer,
1924};
1925
1926int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1927{
1928        struct snd_pcm *pcm;
1929        int err;
1930
1931        err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1932        if (err < 0)
1933                return err;
1934
1935        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1936        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1937
1938        /* global setup */
1939        pcm->private_data = chip;
1940        pcm->info_flags = 0;
1941        if (chip->single_dma)
1942                pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1943        if (chip->hardware != WSS_HW_INTERWAVE)
1944                pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1945        strcpy(pcm->name, snd_wss_chip_id(chip));
1946
1947        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1948                                              snd_dma_isa_data(),
1949                                              64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1950
1951        chip->pcm = pcm;
1952        if (rpcm)
1953                *rpcm = pcm;
1954        return 0;
1955}
1956EXPORT_SYMBOL(snd_wss_pcm);
1957
1958static void snd_wss_timer_free(struct snd_timer *timer)
1959{
1960        struct snd_wss *chip = timer->private_data;
1961        chip->timer = NULL;
1962}
1963
1964int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer)
1965{
1966        struct snd_timer *timer;
1967        struct snd_timer_id tid;
1968        int err;
1969
1970        /* Timer initialization */
1971        tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1972        tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1973        tid.card = chip->card->number;
1974        tid.device = device;
1975        tid.subdevice = 0;
1976        if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1977                return err;
1978        strcpy(timer->name, snd_wss_chip_id(chip));
1979        timer->private_data = chip;
1980        timer->private_free = snd_wss_timer_free;
1981        timer->hw = snd_wss_timer_table;
1982        chip->timer = timer;
1983        if (rtimer)
1984                *rtimer = timer;
1985        return 0;
1986}
1987EXPORT_SYMBOL(snd_wss_timer);
1988
1989/*
1990 *  MIXER part
1991 */
1992
1993static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
1994                            struct snd_ctl_elem_info *uinfo)
1995{
1996        static char *texts[4] = {
1997                "Line", "Aux", "Mic", "Mix"
1998        };
1999        static char *opl3sa_texts[4] = {
2000                "Line", "CD", "Mic", "Mix"
2001        };
2002        static char *gusmax_texts[4] = {
2003                "Line", "Synth", "Mic", "Mix"
2004        };
2005        char **ptexts = texts;
2006        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2007
2008        if (snd_BUG_ON(!chip->card))
2009                return -EINVAL;
2010        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2011        uinfo->count = 2;
2012        uinfo->value.enumerated.items = 4;
2013        if (uinfo->value.enumerated.item > 3)
2014                uinfo->value.enumerated.item = 3;
2015        if (!strcmp(chip->card->driver, "GUS MAX"))
2016                ptexts = gusmax_texts;
2017        switch (chip->hardware) {
2018        case WSS_HW_INTERWAVE:
2019                ptexts = gusmax_texts;
2020                break;
2021        case WSS_HW_OPTI93X:
2022        case WSS_HW_OPL3SA2:
2023                ptexts = opl3sa_texts;
2024                break;
2025        }
2026        strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
2027        return 0;
2028}
2029
2030static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
2031                           struct snd_ctl_elem_value *ucontrol)
2032{
2033        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2034        unsigned long flags;
2035
2036        spin_lock_irqsave(&chip->reg_lock, flags);
2037        ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
2038        ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
2039        spin_unlock_irqrestore(&chip->reg_lock, flags);
2040        return 0;
2041}
2042
2043static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
2044                           struct snd_ctl_elem_value *ucontrol)
2045{
2046        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2047        unsigned long flags;
2048        unsigned short left, right;
2049        int change;
2050
2051        if (ucontrol->value.enumerated.item[0] > 3 ||
2052            ucontrol->value.enumerated.item[1] > 3)
2053                return -EINVAL;
2054        left = ucontrol->value.enumerated.item[0] << 6;
2055        right = ucontrol->value.enumerated.item[1] << 6;
2056        spin_lock_irqsave(&chip->reg_lock, flags);
2057        left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
2058        right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
2059        change = left != chip->image[CS4231_LEFT_INPUT] ||
2060                 right != chip->image[CS4231_RIGHT_INPUT];
2061        snd_wss_out(chip, CS4231_LEFT_INPUT, left);
2062        snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
2063        spin_unlock_irqrestore(&chip->reg_lock, flags);
2064        return change;
2065}
2066
2067int snd_wss_info_single(struct snd_kcontrol *kcontrol,
2068                        struct snd_ctl_elem_info *uinfo)
2069{
2070        int mask = (kcontrol->private_value >> 16) & 0xff;
2071
2072        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2073        uinfo->count = 1;
2074        uinfo->value.integer.min = 0;
2075        uinfo->value.integer.max = mask;
2076        return 0;
2077}
2078EXPORT_SYMBOL(snd_wss_info_single);
2079
2080int snd_wss_get_single(struct snd_kcontrol *kcontrol,
2081                       struct snd_ctl_elem_value *ucontrol)
2082{
2083        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2084        unsigned long flags;
2085        int reg = kcontrol->private_value & 0xff;
2086        int shift = (kcontrol->private_value >> 8) & 0xff;
2087        int mask = (kcontrol->private_value >> 16) & 0xff;
2088        int invert = (kcontrol->private_value >> 24) & 0xff;
2089
2090        spin_lock_irqsave(&chip->reg_lock, flags);
2091        ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
2092        spin_unlock_irqrestore(&chip->reg_lock, flags);
2093        if (invert)
2094                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2095        return 0;
2096}
2097EXPORT_SYMBOL(snd_wss_get_single);
2098
2099int snd_wss_put_single(struct snd_kcontrol *kcontrol,
2100                       struct snd_ctl_elem_value *ucontrol)
2101{
2102        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2103        unsigned long flags;
2104        int reg = kcontrol->private_value & 0xff;
2105        int shift = (kcontrol->private_value >> 8) & 0xff;
2106        int mask = (kcontrol->private_value >> 16) & 0xff;
2107        int invert = (kcontrol->private_value >> 24) & 0xff;
2108        int change;
2109        unsigned short val;
2110
2111        val = (ucontrol->value.integer.value[0] & mask);
2112        if (invert)
2113                val = mask - val;
2114        val <<= shift;
2115        spin_lock_irqsave(&chip->reg_lock, flags);
2116        val = (chip->image[reg] & ~(mask << shift)) | val;
2117        change = val != chip->image[reg];
2118        snd_wss_out(chip, reg, val);
2119        spin_unlock_irqrestore(&chip->reg_lock, flags);
2120        return change;
2121}
2122EXPORT_SYMBOL(snd_wss_put_single);
2123
2124int snd_wss_info_double(struct snd_kcontrol *kcontrol,
2125                        struct snd_ctl_elem_info *uinfo)
2126{
2127        int mask = (kcontrol->private_value >> 24) & 0xff;
2128
2129        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2130        uinfo->count = 2;
2131        uinfo->value.integer.min = 0;
2132        uinfo->value.integer.max = mask;
2133        return 0;
2134}
2135EXPORT_SYMBOL(snd_wss_info_double);
2136
2137int snd_wss_get_double(struct snd_kcontrol *kcontrol,
2138                       struct snd_ctl_elem_value *ucontrol)
2139{
2140        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2141        unsigned long flags;
2142        int left_reg = kcontrol->private_value & 0xff;
2143        int right_reg = (kcontrol->private_value >> 8) & 0xff;
2144        int shift_left = (kcontrol->private_value >> 16) & 0x07;
2145        int shift_right = (kcontrol->private_value >> 19) & 0x07;
2146        int mask = (kcontrol->private_value >> 24) & 0xff;
2147        int invert = (kcontrol->private_value >> 22) & 1;
2148
2149        spin_lock_irqsave(&chip->reg_lock, flags);
2150        ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
2151        ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
2152        spin_unlock_irqrestore(&chip->reg_lock, flags);
2153        if (invert) {
2154                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2155                ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
2156        }
2157        return 0;
2158}
2159EXPORT_SYMBOL(snd_wss_get_double);
2160
2161int snd_wss_put_double(struct snd_kcontrol *kcontrol,
2162                       struct snd_ctl_elem_value *ucontrol)
2163{
2164        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2165        unsigned long flags;
2166        int left_reg = kcontrol->private_value & 0xff;
2167        int right_reg = (kcontrol->private_value >> 8) & 0xff;
2168        int shift_left = (kcontrol->private_value >> 16) & 0x07;
2169        int shift_right = (kcontrol->private_value >> 19) & 0x07;
2170        int mask = (kcontrol->private_value >> 24) & 0xff;
2171        int invert = (kcontrol->private_value >> 22) & 1;
2172        int change;
2173        unsigned short val1, val2;
2174
2175        val1 = ucontrol->value.integer.value[0] & mask;
2176        val2 = ucontrol->value.integer.value[1] & mask;
2177        if (invert) {
2178                val1 = mask - val1;
2179                val2 = mask - val2;
2180        }
2181        val1 <<= shift_left;
2182        val2 <<= shift_right;
2183        spin_lock_irqsave(&chip->reg_lock, flags);
2184        if (left_reg != right_reg) {
2185                val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
2186                val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
2187                change = val1 != chip->image[left_reg] ||
2188                         val2 != chip->image[right_reg];
2189                snd_wss_out(chip, left_reg, val1);
2190                snd_wss_out(chip, right_reg, val2);
2191        } else {
2192                mask = (mask << shift_left) | (mask << shift_right);
2193                val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
2194                change = val1 != chip->image[left_reg];
2195                snd_wss_out(chip, left_reg, val1);
2196        }
2197        spin_unlock_irqrestore(&chip->reg_lock, flags);
2198        return change;
2199}
2200EXPORT_SYMBOL(snd_wss_put_double);
2201
2202static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
2203static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
2204static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
2205static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
2206
2207static struct snd_kcontrol_new snd_wss_controls[] = {
2208WSS_DOUBLE("PCM Playback Switch", 0,
2209                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2210WSS_DOUBLE_TLV("PCM Playback Volume", 0,
2211                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
2212                db_scale_6bit),
2213WSS_DOUBLE("Aux Playback Switch", 0,
2214                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2215WSS_DOUBLE_TLV("Aux Playback Volume", 0,
2216                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
2217                db_scale_5bit_12db_max),
2218WSS_DOUBLE("Aux Playback Switch", 1,
2219                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2220WSS_DOUBLE_TLV("Aux Playback Volume", 1,
2221                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
2222                db_scale_5bit_12db_max),
2223WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
2224                0, 0, 15, 0, db_scale_rec_gain),
2225{
2226        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2227        .name = "Capture Source",
2228        .info = snd_wss_info_mux,
2229        .get = snd_wss_get_mux,
2230        .put = snd_wss_put_mux,
2231},
2232WSS_DOUBLE("Mic Boost (+20dB)", 0,
2233                CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2234WSS_SINGLE("Loopback Capture Switch", 0,
2235                CS4231_LOOPBACK, 0, 1, 0),
2236WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1,
2237                db_scale_6bit),
2238WSS_DOUBLE("Line Playback Switch", 0,
2239                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2240WSS_DOUBLE_TLV("Line Playback Volume", 0,
2241                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
2242                db_scale_5bit_12db_max),
2243WSS_SINGLE("Beep Playback Switch", 0,
2244                CS4231_MONO_CTRL, 7, 1, 1),
2245WSS_SINGLE_TLV("Beep Playback Volume", 0,
2246                CS4231_MONO_CTRL, 0, 15, 1,
2247                db_scale_4bit),
2248WSS_SINGLE("Mono Output Playback Switch", 0,
2249                CS4231_MONO_CTRL, 6, 1, 1),
2250WSS_SINGLE("Beep Bypass Playback Switch", 0,
2251                CS4231_MONO_CTRL, 5, 1, 0),
2252};
2253
2254int snd_wss_mixer(struct snd_wss *chip)
2255{
2256        struct snd_card *card;
2257        unsigned int idx;
2258        int err;
2259        int count = ARRAY_SIZE(snd_wss_controls);
2260
2261        if (snd_BUG_ON(!chip || !chip->pcm))
2262                return -EINVAL;
2263
2264        card = chip->card;
2265
2266        strcpy(card->mixername, chip->pcm->name);
2267
2268        /* Use only the first 11 entries on AD1848 */
2269        if (chip->hardware & WSS_HW_AD1848_MASK)
2270                count = 11;
2271        /* There is no loopback on OPTI93X */
2272        else if (chip->hardware == WSS_HW_OPTI93X)
2273                count = 9;
2274
2275        for (idx = 0; idx < count; idx++) {
2276                err = snd_ctl_add(card,
2277                                snd_ctl_new1(&snd_wss_controls[idx],
2278                                             chip));
2279                if (err < 0)
2280                        return err;
2281        }
2282        return 0;
2283}
2284EXPORT_SYMBOL(snd_wss_mixer);
2285
2286const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2287{
2288        return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2289                &snd_wss_playback_ops : &snd_wss_capture_ops;
2290}
2291EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2292
2293/*
2294 *  INIT part
2295 */
2296
2297static int __init alsa_wss_init(void)
2298{
2299        return 0;
2300}
2301
2302static void __exit alsa_wss_exit(void)
2303{
2304}
2305
2306module_init(alsa_wss_init);
2307module_exit(alsa_wss_exit);
2308