linux/sound/isa/es1688/es1688_lib.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   3 *  Routines for control of ESS ES1688/688/488 chip
   4 *
   5 *
   6 *   This program is free software; you can redistribute it and/or modify
   7 *   it under the terms of the GNU General Public License as published by
   8 *   the Free Software Foundation; either version 2 of the License, or
   9 *   (at your option) any later version.
  10 *
  11 *   This program is distributed in the hope that it will be useful,
  12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *   GNU General Public License for more details.
  15 *
  16 *   You should have received a copy of the GNU General Public License
  17 *   along with this program; if not, write to the Free Software
  18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19 *
  20 */
  21
  22#include <linux/init.h>
  23#include <linux/interrupt.h>
  24#include <linux/delay.h>
  25#include <linux/slab.h>
  26#include <linux/ioport.h>
  27#include <linux/module.h>
  28#include <linux/io.h>
  29#include <sound/core.h>
  30#include <sound/es1688.h>
  31#include <sound/initval.h>
  32
  33#include <asm/dma.h>
  34
  35MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  36MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
  37MODULE_LICENSE("GPL");
  38
  39static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val)
  40{
  41        int i;
  42
  43        for (i = 10000; i; i--)
  44                if ((inb(ES1688P(chip, STATUS)) & 0x80) == 0) {
  45                        outb(val, ES1688P(chip, COMMAND));
  46                        return 1;
  47                }
  48#ifdef CONFIG_SND_DEBUG
  49        printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val);
  50#endif
  51        return 0;
  52}
  53
  54static int snd_es1688_dsp_get_byte(struct snd_es1688 *chip)
  55{
  56        int i;
  57
  58        for (i = 1000; i; i--)
  59                if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80)
  60                        return inb(ES1688P(chip, READ));
  61        snd_printd("es1688 get byte failed: 0x%lx = 0x%x!!!\n", ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL)));
  62        return -ENODEV;
  63}
  64
  65static int snd_es1688_write(struct snd_es1688 *chip,
  66                            unsigned char reg, unsigned char data)
  67{
  68        if (!snd_es1688_dsp_command(chip, reg))
  69                return 0;
  70        return snd_es1688_dsp_command(chip, data);
  71}
  72
  73static int snd_es1688_read(struct snd_es1688 *chip, unsigned char reg)
  74{
  75        /* Read a byte from an extended mode register of ES1688 */
  76        if (!snd_es1688_dsp_command(chip, 0xc0))
  77                return -1;
  78        if (!snd_es1688_dsp_command(chip, reg))
  79                return -1;
  80        return snd_es1688_dsp_get_byte(chip);
  81}
  82
  83void snd_es1688_mixer_write(struct snd_es1688 *chip,
  84                            unsigned char reg, unsigned char data)
  85{
  86        outb(reg, ES1688P(chip, MIXER_ADDR));
  87        udelay(10);
  88        outb(data, ES1688P(chip, MIXER_DATA));
  89        udelay(10);
  90}
  91
  92static unsigned char snd_es1688_mixer_read(struct snd_es1688 *chip, unsigned char reg)
  93{
  94        unsigned char result;
  95
  96        outb(reg, ES1688P(chip, MIXER_ADDR));
  97        udelay(10);
  98        result = inb(ES1688P(chip, MIXER_DATA));
  99        udelay(10);
 100        return result;
 101}
 102
 103int snd_es1688_reset(struct snd_es1688 *chip)
 104{
 105        int i;
 106
 107        outb(3, ES1688P(chip, RESET));          /* valid only for ESS chips, SB -> 1 */
 108        udelay(10);
 109        outb(0, ES1688P(chip, RESET));
 110        udelay(30);
 111        for (i = 0; i < 1000 && !(inb(ES1688P(chip, DATA_AVAIL)) & 0x80); i++);
 112        if (inb(ES1688P(chip, READ)) != 0xaa) {
 113                snd_printd("ess_reset at 0x%lx: failed!!!\n", chip->port);
 114                return -ENODEV;
 115        }
 116        snd_es1688_dsp_command(chip, 0xc6);     /* enable extended mode */
 117        return 0;
 118}
 119EXPORT_SYMBOL(snd_es1688_reset);
 120
 121static int snd_es1688_probe(struct snd_es1688 *chip)
 122{
 123        unsigned long flags;
 124        unsigned short major, minor, hw;
 125        int i;
 126
 127        /*
 128         *  initialization sequence
 129         */
 130
 131        spin_lock_irqsave(&chip->reg_lock, flags);      /* Some ESS1688 cards need this */
 132        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 133        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 134        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 135        inb(ES1688P(chip, ENABLE2));    /* ENABLE2 */
 136        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 137        inb(ES1688P(chip, ENABLE2));    /* ENABLE2 */
 138        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 139        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 140        inb(ES1688P(chip, ENABLE2));    /* ENABLE2 */
 141        inb(ES1688P(chip, ENABLE1));    /* ENABLE1 */
 142        inb(ES1688P(chip, ENABLE0));    /* ENABLE0 */
 143
 144        if (snd_es1688_reset(chip) < 0) {
 145                snd_printdd("ESS: [0x%lx] reset failed... 0x%x\n", chip->port, inb(ES1688P(chip, READ)));
 146                spin_unlock_irqrestore(&chip->reg_lock, flags);
 147                return -ENODEV;
 148        }
 149        snd_es1688_dsp_command(chip, 0xe7);     /* return identification */
 150
 151        for (i = 1000, major = minor = 0; i; i--) {
 152                if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) {
 153                        if (major == 0) {
 154                                major = inb(ES1688P(chip, READ));
 155                        } else {
 156                                minor = inb(ES1688P(chip, READ));
 157                        }
 158                }
 159        }
 160
 161        spin_unlock_irqrestore(&chip->reg_lock, flags);
 162
 163        snd_printdd("ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", chip->port, major, minor);
 164
 165        chip->version = (major << 8) | minor;
 166        if (!chip->version)
 167                return -ENODEV; /* probably SB */
 168
 169        hw = ES1688_HW_AUTO;
 170        switch (chip->version & 0xfff0) {
 171        case 0x4880:
 172                snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, "
 173                           "but driver is in another place\n", chip->port);
 174                return -ENODEV;
 175        case 0x6880:
 176                hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688;
 177                break;
 178        default:
 179                snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip "
 180                           "with version 0x%x (Jazz16 soundcard?)\n",
 181                           chip->port, chip->version);
 182                return -ENODEV;
 183        }
 184
 185        spin_lock_irqsave(&chip->reg_lock, flags);
 186        snd_es1688_write(chip, 0xb1, 0x10);     /* disable IRQ */
 187        snd_es1688_write(chip, 0xb2, 0x00);     /* disable DMA */
 188        spin_unlock_irqrestore(&chip->reg_lock, flags);
 189
 190        /* enable joystick, but disable OPL3 */
 191        spin_lock_irqsave(&chip->mixer_lock, flags);
 192        snd_es1688_mixer_write(chip, 0x40, 0x01);
 193        spin_unlock_irqrestore(&chip->mixer_lock, flags);
 194
 195        return 0;
 196}
 197
 198static int snd_es1688_init(struct snd_es1688 * chip, int enable)
 199{
 200        static int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1};
 201        unsigned long flags;
 202        int cfg, irq_bits, dma, dma_bits, tmp, tmp1;
 203
 204        /* ok.. setup MPU-401 port and joystick and OPL3 */
 205        cfg = 0x01;             /* enable joystick, but disable OPL3 */
 206        if (enable && chip->mpu_port >= 0x300 && chip->mpu_irq > 0 && chip->hardware != ES1688_HW_688) {
 207                tmp = (chip->mpu_port & 0x0f0) >> 4;
 208                if (tmp <= 3) {
 209                        switch (chip->mpu_irq) {
 210                        case 9:
 211                                tmp1 = 4;
 212                                break;
 213                        case 5:
 214                                tmp1 = 5;
 215                                break;
 216                        case 7:
 217                                tmp1 = 6;
 218                                break;
 219                        case 10:
 220                                tmp1 = 7;
 221                                break;
 222                        default:
 223                                tmp1 = 0;
 224                        }
 225                        if (tmp1) {
 226                                cfg |= (tmp << 3) | (tmp1 << 5);
 227                        }
 228                }
 229        }
 230#if 0
 231        snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg);
 232#endif
 233        spin_lock_irqsave(&chip->reg_lock, flags);
 234        snd_es1688_mixer_write(chip, 0x40, cfg);
 235        spin_unlock_irqrestore(&chip->reg_lock, flags);
 236        /* --- */
 237        spin_lock_irqsave(&chip->reg_lock, flags);
 238        snd_es1688_read(chip, 0xb1);
 239        snd_es1688_read(chip, 0xb2);
 240        spin_unlock_irqrestore(&chip->reg_lock, flags);
 241        if (enable) {
 242                cfg = 0xf0;     /* enable only DMA counter interrupt */
 243                irq_bits = irqs[chip->irq & 0x0f];
 244                if (irq_bits < 0) {
 245                        snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d "
 246                                   "for ES1688 chip!!\n",
 247                                   chip->port, chip->irq);
 248#if 0
 249                        irq_bits = 0;
 250                        cfg = 0x10;
 251#endif
 252                        return -EINVAL;
 253                }
 254                spin_lock_irqsave(&chip->reg_lock, flags);
 255                snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2));
 256                spin_unlock_irqrestore(&chip->reg_lock, flags);
 257                cfg = 0xf0;     /* extended mode DMA enable */
 258                dma = chip->dma8;
 259                if (dma > 3 || dma == 2) {
 260                        snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d "
 261                                   "for ES1688 chip!!\n", chip->port, dma);
 262#if 0
 263                        dma_bits = 0;
 264                        cfg = 0x00;     /* disable all DMA */
 265#endif
 266                        return -EINVAL;
 267                } else {
 268                        dma_bits = dma;
 269                        if (dma != 3)
 270                                dma_bits++;
 271                }
 272                spin_lock_irqsave(&chip->reg_lock, flags);
 273                snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2));
 274                spin_unlock_irqrestore(&chip->reg_lock, flags);
 275        } else {
 276                spin_lock_irqsave(&chip->reg_lock, flags);
 277                snd_es1688_write(chip, 0xb1, 0x10);     /* disable IRQ */
 278                snd_es1688_write(chip, 0xb2, 0x00);     /* disable DMA */
 279                spin_unlock_irqrestore(&chip->reg_lock, flags);
 280        }
 281        spin_lock_irqsave(&chip->reg_lock, flags);
 282        snd_es1688_read(chip, 0xb1);
 283        snd_es1688_read(chip, 0xb2);
 284        snd_es1688_reset(chip);
 285        spin_unlock_irqrestore(&chip->reg_lock, flags);
 286        return 0;
 287}
 288
 289/*
 290
 291 */
 292
 293static const struct snd_ratnum clocks[2] = {
 294        {
 295                .num = 795444,
 296                .den_min = 1,
 297                .den_max = 128,
 298                .den_step = 1,
 299        },
 300        {
 301                .num = 397722,
 302                .den_min = 1,
 303                .den_max = 128,
 304                .den_step = 1,
 305        }
 306};
 307
 308static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks  = {
 309        .nrats = 2,
 310        .rats = clocks,
 311};
 312
 313static void snd_es1688_set_rate(struct snd_es1688 *chip, struct snd_pcm_substream *substream)
 314{
 315        struct snd_pcm_runtime *runtime = substream->runtime;
 316        unsigned int bits, divider;
 317
 318        if (runtime->rate_num == clocks[0].num)
 319                bits = 256 - runtime->rate_den;
 320        else
 321                bits = 128 - runtime->rate_den;
 322        /* set filter register */
 323        divider = 256 - 7160000*20/(8*82*runtime->rate);
 324        /* write result to hardware */
 325        snd_es1688_write(chip, 0xa1, bits);
 326        snd_es1688_write(chip, 0xa2, divider);
 327}
 328
 329static int snd_es1688_ioctl(struct snd_pcm_substream *substream,
 330                            unsigned int cmd, void *arg)
 331{
 332        return snd_pcm_lib_ioctl(substream, cmd, arg);
 333}
 334
 335static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char value)
 336{
 337        int val;
 338
 339        if (cmd == SNDRV_PCM_TRIGGER_STOP) {
 340                value = 0x00;
 341        } else if (cmd != SNDRV_PCM_TRIGGER_START) {
 342                return -EINVAL;
 343        }
 344        spin_lock(&chip->reg_lock);
 345        chip->trigger_value = value;
 346        val = snd_es1688_read(chip, 0xb8);
 347        if ((val < 0) || (val & 0x0f) == value) {
 348                spin_unlock(&chip->reg_lock);
 349                return -EINVAL; /* something is wrong */
 350        }
 351#if 0
 352        printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value);
 353        printk(KERN_DEBUG "trigger: pointer = 0x%x\n",
 354               snd_dma_pointer(chip->dma8, chip->dma_size));
 355#endif
 356        snd_es1688_write(chip, 0xb8, (val & 0xf0) | value);
 357        spin_unlock(&chip->reg_lock);
 358        return 0;
 359}
 360
 361static int snd_es1688_hw_params(struct snd_pcm_substream *substream,
 362                                struct snd_pcm_hw_params *hw_params)
 363{
 364        return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 365}
 366
 367static int snd_es1688_hw_free(struct snd_pcm_substream *substream)
 368{
 369        return snd_pcm_lib_free_pages(substream);
 370}
 371
 372static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream)
 373{
 374        unsigned long flags;
 375        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 376        struct snd_pcm_runtime *runtime = substream->runtime;
 377        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
 378        unsigned int count = snd_pcm_lib_period_bytes(substream);
 379
 380        chip->dma_size = size;
 381        spin_lock_irqsave(&chip->reg_lock, flags);
 382        snd_es1688_reset(chip);
 383        snd_es1688_set_rate(chip, substream);
 384        snd_es1688_write(chip, 0xb8, 4);        /* auto init DMA mode */
 385        snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels));
 386        snd_es1688_write(chip, 0xb9, 2);        /* demand mode (4 bytes/request) */
 387        if (runtime->channels == 1) {
 388                if (snd_pcm_format_width(runtime->format) == 8) {
 389                        /* 8. bit mono */
 390                        snd_es1688_write(chip, 0xb6, 0x80);
 391                        snd_es1688_write(chip, 0xb7, 0x51);
 392                        snd_es1688_write(chip, 0xb7, 0xd0);
 393                } else {
 394                        /* 16. bit mono */
 395                        snd_es1688_write(chip, 0xb6, 0x00);
 396                        snd_es1688_write(chip, 0xb7, 0x71);
 397                        snd_es1688_write(chip, 0xb7, 0xf4);
 398                }
 399        } else {
 400                if (snd_pcm_format_width(runtime->format) == 8) {
 401                        /* 8. bit stereo */
 402                        snd_es1688_write(chip, 0xb6, 0x80);
 403                        snd_es1688_write(chip, 0xb7, 0x51);
 404                        snd_es1688_write(chip, 0xb7, 0x98);
 405                } else {
 406                        /* 16. bit stereo */
 407                        snd_es1688_write(chip, 0xb6, 0x00);
 408                        snd_es1688_write(chip, 0xb7, 0x71);
 409                        snd_es1688_write(chip, 0xb7, 0xbc);
 410                }
 411        }
 412        snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50);
 413        snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50);
 414        snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON);
 415        spin_unlock_irqrestore(&chip->reg_lock, flags);
 416        /* --- */
 417        count = -count;
 418        snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
 419        spin_lock_irqsave(&chip->reg_lock, flags);
 420        snd_es1688_write(chip, 0xa4, (unsigned char) count);
 421        snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8));
 422        spin_unlock_irqrestore(&chip->reg_lock, flags);
 423        return 0;
 424}
 425
 426static int snd_es1688_playback_trigger(struct snd_pcm_substream *substream,
 427                                       int cmd)
 428{
 429        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 430        return snd_es1688_trigger(chip, cmd, 0x05);
 431}
 432
 433static int snd_es1688_capture_prepare(struct snd_pcm_substream *substream)
 434{
 435        unsigned long flags;
 436        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 437        struct snd_pcm_runtime *runtime = substream->runtime;
 438        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
 439        unsigned int count = snd_pcm_lib_period_bytes(substream);
 440
 441        chip->dma_size = size;
 442        spin_lock_irqsave(&chip->reg_lock, flags);
 443        snd_es1688_reset(chip);
 444        snd_es1688_set_rate(chip, substream);
 445        snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF);
 446        snd_es1688_write(chip, 0xb8, 0x0e);     /* auto init DMA mode */
 447        snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels));
 448        snd_es1688_write(chip, 0xb9, 2);        /* demand mode (4 bytes/request) */
 449        if (runtime->channels == 1) {
 450                if (snd_pcm_format_width(runtime->format) == 8) {
 451                        /* 8. bit mono */
 452                        snd_es1688_write(chip, 0xb7, 0x51);
 453                        snd_es1688_write(chip, 0xb7, 0xd0);
 454                } else {
 455                        /* 16. bit mono */
 456                        snd_es1688_write(chip, 0xb7, 0x71);
 457                        snd_es1688_write(chip, 0xb7, 0xf4);
 458                }
 459        } else {
 460                if (snd_pcm_format_width(runtime->format) == 8) {
 461                        /* 8. bit stereo */
 462                        snd_es1688_write(chip, 0xb7, 0x51);
 463                        snd_es1688_write(chip, 0xb7, 0x98);
 464                } else {
 465                        /* 16. bit stereo */
 466                        snd_es1688_write(chip, 0xb7, 0x71);
 467                        snd_es1688_write(chip, 0xb7, 0xbc);
 468                }
 469        }
 470        snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50);
 471        snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50);
 472        spin_unlock_irqrestore(&chip->reg_lock, flags);
 473        /* --- */
 474        count = -count;
 475        snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
 476        spin_lock_irqsave(&chip->reg_lock, flags);
 477        snd_es1688_write(chip, 0xa4, (unsigned char) count);
 478        snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8));
 479        spin_unlock_irqrestore(&chip->reg_lock, flags);
 480        return 0;
 481}
 482
 483static int snd_es1688_capture_trigger(struct snd_pcm_substream *substream,
 484                                      int cmd)
 485{
 486        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 487        return snd_es1688_trigger(chip, cmd, 0x0f);
 488}
 489
 490static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id)
 491{
 492        struct snd_es1688 *chip = dev_id;
 493
 494        if (chip->trigger_value == 0x05)        /* ok.. playback is active */
 495                snd_pcm_period_elapsed(chip->playback_substream);
 496        if (chip->trigger_value == 0x0f)        /* ok.. capture is active */
 497                snd_pcm_period_elapsed(chip->capture_substream);
 498
 499        inb(ES1688P(chip, DATA_AVAIL)); /* ack interrupt */
 500        return IRQ_HANDLED;
 501}
 502
 503static snd_pcm_uframes_t snd_es1688_playback_pointer(struct snd_pcm_substream *substream)
 504{
 505        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 506        size_t ptr;
 507        
 508        if (chip->trigger_value != 0x05)
 509                return 0;
 510        ptr = snd_dma_pointer(chip->dma8, chip->dma_size);
 511        return bytes_to_frames(substream->runtime, ptr);
 512}
 513
 514static snd_pcm_uframes_t snd_es1688_capture_pointer(struct snd_pcm_substream *substream)
 515{
 516        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 517        size_t ptr;
 518        
 519        if (chip->trigger_value != 0x0f)
 520                return 0;
 521        ptr = snd_dma_pointer(chip->dma8, chip->dma_size);
 522        return bytes_to_frames(substream->runtime, ptr);
 523}
 524
 525/*
 526
 527 */
 528
 529static const struct snd_pcm_hardware snd_es1688_playback =
 530{
 531        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 532                                 SNDRV_PCM_INFO_MMAP_VALID),
 533        .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 534        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 535        .rate_min =             4000,
 536        .rate_max =             48000,
 537        .channels_min =         1,
 538        .channels_max =         2,
 539        .buffer_bytes_max =     65536,
 540        .period_bytes_min =     64,
 541        .period_bytes_max =     65536,
 542        .periods_min =          1,
 543        .periods_max =          1024,
 544        .fifo_size =            0,
 545};
 546
 547static const struct snd_pcm_hardware snd_es1688_capture =
 548{
 549        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 550                                 SNDRV_PCM_INFO_MMAP_VALID),
 551        .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 552        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 553        .rate_min =             4000,
 554        .rate_max =             48000,
 555        .channels_min =         1,
 556        .channels_max =         2,
 557        .buffer_bytes_max =     65536,
 558        .period_bytes_min =     64,
 559        .period_bytes_max =     65536,
 560        .periods_min =          1,
 561        .periods_max =          1024,
 562        .fifo_size =            0,
 563};
 564
 565/*
 566
 567 */
 568
 569static int snd_es1688_playback_open(struct snd_pcm_substream *substream)
 570{
 571        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 572        struct snd_pcm_runtime *runtime = substream->runtime;
 573
 574        if (chip->capture_substream != NULL)
 575                return -EAGAIN;
 576        chip->playback_substream = substream;
 577        runtime->hw = snd_es1688_playback;
 578        snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 579                                      &hw_constraints_clocks);
 580        return 0;
 581}
 582
 583static int snd_es1688_capture_open(struct snd_pcm_substream *substream)
 584{
 585        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 586        struct snd_pcm_runtime *runtime = substream->runtime;
 587
 588        if (chip->playback_substream != NULL)
 589                return -EAGAIN;
 590        chip->capture_substream = substream;
 591        runtime->hw = snd_es1688_capture;
 592        snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 593                                      &hw_constraints_clocks);
 594        return 0;
 595}
 596
 597static int snd_es1688_playback_close(struct snd_pcm_substream *substream)
 598{
 599        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 600
 601        chip->playback_substream = NULL;
 602        return 0;
 603}
 604
 605static int snd_es1688_capture_close(struct snd_pcm_substream *substream)
 606{
 607        struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
 608
 609        chip->capture_substream = NULL;
 610        return 0;
 611}
 612
 613static int snd_es1688_free(struct snd_es1688 *chip)
 614{
 615        if (chip->hardware != ES1688_HW_UNDEF)
 616                snd_es1688_init(chip, 0);
 617        release_and_free_resource(chip->res_port);
 618        if (chip->irq >= 0)
 619                free_irq(chip->irq, (void *) chip);
 620        if (chip->dma8 >= 0) {
 621                disable_dma(chip->dma8);
 622                free_dma(chip->dma8);
 623        }
 624        return 0;
 625}
 626
 627static int snd_es1688_dev_free(struct snd_device *device)
 628{
 629        struct snd_es1688 *chip = device->device_data;
 630        return snd_es1688_free(chip);
 631}
 632
 633static const char *snd_es1688_chip_id(struct snd_es1688 *chip)
 634{
 635        static char tmp[16];
 636        sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f);
 637        return tmp;
 638}
 639
 640int snd_es1688_create(struct snd_card *card,
 641                      struct snd_es1688 *chip,
 642                      unsigned long port,
 643                      unsigned long mpu_port,
 644                      int irq,
 645                      int mpu_irq,
 646                      int dma8,
 647                      unsigned short hardware)
 648{
 649        static struct snd_device_ops ops = {
 650                .dev_free =     snd_es1688_dev_free,
 651        };
 652                                
 653        int err;
 654
 655        if (chip == NULL)
 656                return -ENOMEM;
 657        chip->irq = -1;
 658        chip->dma8 = -1;
 659        chip->hardware = ES1688_HW_UNDEF;
 660        
 661        chip->res_port = request_region(port + 4, 12, "ES1688");
 662        if (chip->res_port == NULL) {
 663                snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4);
 664                err = -EBUSY;
 665                goto exit;
 666        }
 667
 668        err = request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip);
 669        if (err < 0) {
 670                snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq);
 671                goto exit;
 672        }
 673
 674        chip->irq = irq;
 675        err = request_dma(dma8, "ES1688");
 676
 677        if (err < 0) {
 678                snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8);
 679                goto exit;
 680        }
 681        chip->dma8 = dma8;
 682
 683        spin_lock_init(&chip->reg_lock);
 684        spin_lock_init(&chip->mixer_lock);
 685        chip->port = port;
 686        mpu_port &= ~0x000f;
 687        if (mpu_port < 0x300 || mpu_port > 0x330)
 688                mpu_port = 0;
 689        chip->mpu_port = mpu_port;
 690        chip->mpu_irq = mpu_irq;
 691        chip->hardware = hardware;
 692
 693        err = snd_es1688_probe(chip);
 694        if (err < 0)
 695                goto exit;
 696
 697        err = snd_es1688_init(chip, 1);
 698        if (err < 0)
 699                goto exit;
 700
 701        /* Register device */
 702        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
 703exit:
 704        if (err)
 705                snd_es1688_free(chip);
 706        return err;
 707}
 708
 709static const struct snd_pcm_ops snd_es1688_playback_ops = {
 710        .open =                 snd_es1688_playback_open,
 711        .close =                snd_es1688_playback_close,
 712        .ioctl =                snd_es1688_ioctl,
 713        .hw_params =            snd_es1688_hw_params,
 714        .hw_free =              snd_es1688_hw_free,
 715        .prepare =              snd_es1688_playback_prepare,
 716        .trigger =              snd_es1688_playback_trigger,
 717        .pointer =              snd_es1688_playback_pointer,
 718};
 719
 720static const struct snd_pcm_ops snd_es1688_capture_ops = {
 721        .open =                 snd_es1688_capture_open,
 722        .close =                snd_es1688_capture_close,
 723        .ioctl =                snd_es1688_ioctl,
 724        .hw_params =            snd_es1688_hw_params,
 725        .hw_free =              snd_es1688_hw_free,
 726        .prepare =              snd_es1688_capture_prepare,
 727        .trigger =              snd_es1688_capture_trigger,
 728        .pointer =              snd_es1688_capture_pointer,
 729};
 730
 731int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device)
 732{
 733        struct snd_pcm *pcm;
 734        int err;
 735
 736        err = snd_pcm_new(card, "ESx688", device, 1, 1, &pcm);
 737        if (err < 0)
 738                return err;
 739
 740        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1688_playback_ops);
 741        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops);
 742
 743        pcm->private_data = chip;
 744        pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
 745        strcpy(pcm->name, snd_es1688_chip_id(chip));
 746        chip->pcm = pcm;
 747
 748        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 749                                              snd_dma_isa_data(),
 750                                              64*1024, 64*1024);
 751        return 0;
 752}
 753
 754/*
 755 *  MIXER part
 756 */
 757
 758static int snd_es1688_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 759{
 760        static const char * const texts[8] = {
 761                "Mic", "Mic Master", "CD", "AOUT",
 762                "Mic1", "Mix", "Line", "Master"
 763        };
 764
 765        return snd_ctl_enum_info(uinfo, 1, 8, texts);
 766}
 767
 768static int snd_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 769{
 770        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 771        ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7;
 772        return 0;
 773}
 774
 775static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 776{
 777        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 778        unsigned long flags;
 779        unsigned char oval, nval;
 780        int change;
 781        
 782        if (ucontrol->value.enumerated.item[0] > 8)
 783                return -EINVAL;
 784        spin_lock_irqsave(&chip->reg_lock, flags);
 785        oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV);
 786        nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15);
 787        change = nval != oval;
 788        if (change)
 789                snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval);
 790        spin_unlock_irqrestore(&chip->reg_lock, flags);
 791        return change;
 792}
 793
 794#define ES1688_SINGLE(xname, xindex, reg, shift, mask, invert) \
 795{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
 796  .info = snd_es1688_info_single, \
 797  .get = snd_es1688_get_single, .put = snd_es1688_put_single, \
 798  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
 799
 800static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 801{
 802        int mask = (kcontrol->private_value >> 16) & 0xff;
 803
 804        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
 805        uinfo->count = 1;
 806        uinfo->value.integer.min = 0;
 807        uinfo->value.integer.max = mask;
 808        return 0;
 809}
 810
 811static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 812{
 813        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 814        unsigned long flags;
 815        int reg = kcontrol->private_value & 0xff;
 816        int shift = (kcontrol->private_value >> 8) & 0xff;
 817        int mask = (kcontrol->private_value >> 16) & 0xff;
 818        int invert = (kcontrol->private_value >> 24) & 0xff;
 819        
 820        spin_lock_irqsave(&chip->reg_lock, flags);
 821        ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask;
 822        spin_unlock_irqrestore(&chip->reg_lock, flags);
 823        if (invert)
 824                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 825        return 0;
 826}
 827
 828static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 829{
 830        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 831        unsigned long flags;
 832        int reg = kcontrol->private_value & 0xff;
 833        int shift = (kcontrol->private_value >> 8) & 0xff;
 834        int mask = (kcontrol->private_value >> 16) & 0xff;
 835        int invert = (kcontrol->private_value >> 24) & 0xff;
 836        int change;
 837        unsigned char oval, nval;
 838        
 839        nval = (ucontrol->value.integer.value[0] & mask);
 840        if (invert)
 841                nval = mask - nval;
 842        nval <<= shift;
 843        spin_lock_irqsave(&chip->reg_lock, flags);
 844        oval = snd_es1688_mixer_read(chip, reg);
 845        nval = (oval & ~(mask << shift)) | nval;
 846        change = nval != oval;
 847        if (change)
 848                snd_es1688_mixer_write(chip, reg, nval);
 849        spin_unlock_irqrestore(&chip->reg_lock, flags);
 850        return change;
 851}
 852
 853#define ES1688_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
 854{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
 855  .info = snd_es1688_info_double, \
 856  .get = snd_es1688_get_double, .put = snd_es1688_put_double, \
 857  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
 858
 859static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 860{
 861        int mask = (kcontrol->private_value >> 24) & 0xff;
 862
 863        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
 864        uinfo->count = 2;
 865        uinfo->value.integer.min = 0;
 866        uinfo->value.integer.max = mask;
 867        return 0;
 868}
 869
 870static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 871{
 872        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 873        unsigned long flags;
 874        int left_reg = kcontrol->private_value & 0xff;
 875        int right_reg = (kcontrol->private_value >> 8) & 0xff;
 876        int shift_left = (kcontrol->private_value >> 16) & 0x07;
 877        int shift_right = (kcontrol->private_value >> 19) & 0x07;
 878        int mask = (kcontrol->private_value >> 24) & 0xff;
 879        int invert = (kcontrol->private_value >> 22) & 1;
 880        unsigned char left, right;
 881        
 882        spin_lock_irqsave(&chip->reg_lock, flags);
 883        if (left_reg < 0xa0)
 884                left = snd_es1688_mixer_read(chip, left_reg);
 885        else
 886                left = snd_es1688_read(chip, left_reg);
 887        if (left_reg != right_reg) {
 888                if (right_reg < 0xa0) 
 889                        right = snd_es1688_mixer_read(chip, right_reg);
 890                else
 891                        right = snd_es1688_read(chip, right_reg);
 892        } else
 893                right = left;
 894        spin_unlock_irqrestore(&chip->reg_lock, flags);
 895        ucontrol->value.integer.value[0] = (left >> shift_left) & mask;
 896        ucontrol->value.integer.value[1] = (right >> shift_right) & mask;
 897        if (invert) {
 898                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 899                ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
 900        }
 901        return 0;
 902}
 903
 904static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 905{
 906        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 907        unsigned long flags;
 908        int left_reg = kcontrol->private_value & 0xff;
 909        int right_reg = (kcontrol->private_value >> 8) & 0xff;
 910        int shift_left = (kcontrol->private_value >> 16) & 0x07;
 911        int shift_right = (kcontrol->private_value >> 19) & 0x07;
 912        int mask = (kcontrol->private_value >> 24) & 0xff;
 913        int invert = (kcontrol->private_value >> 22) & 1;
 914        int change;
 915        unsigned char val1, val2, oval1, oval2;
 916        
 917        val1 = ucontrol->value.integer.value[0] & mask;
 918        val2 = ucontrol->value.integer.value[1] & mask;
 919        if (invert) {
 920                val1 = mask - val1;
 921                val2 = mask - val2;
 922        }
 923        val1 <<= shift_left;
 924        val2 <<= shift_right;
 925        spin_lock_irqsave(&chip->reg_lock, flags);
 926        if (left_reg != right_reg) {
 927                if (left_reg < 0xa0)
 928                        oval1 = snd_es1688_mixer_read(chip, left_reg);
 929                else
 930                        oval1 = snd_es1688_read(chip, left_reg);
 931                if (right_reg < 0xa0)
 932                        oval2 = snd_es1688_mixer_read(chip, right_reg);
 933                else
 934                        oval2 = snd_es1688_read(chip, right_reg);
 935                val1 = (oval1 & ~(mask << shift_left)) | val1;
 936                val2 = (oval2 & ~(mask << shift_right)) | val2;
 937                change = val1 != oval1 || val2 != oval2;
 938                if (change) {
 939                        if (left_reg < 0xa0)
 940                                snd_es1688_mixer_write(chip, left_reg, val1);
 941                        else
 942                                snd_es1688_write(chip, left_reg, val1);
 943                        if (right_reg < 0xa0)
 944                                snd_es1688_mixer_write(chip, right_reg, val1);
 945                        else
 946                                snd_es1688_write(chip, right_reg, val1);
 947                }
 948        } else {
 949                if (left_reg < 0xa0)
 950                        oval1 = snd_es1688_mixer_read(chip, left_reg);
 951                else
 952                        oval1 = snd_es1688_read(chip, left_reg);
 953                val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
 954                change = val1 != oval1;
 955                if (change) {
 956                        if (left_reg < 0xa0)
 957                                snd_es1688_mixer_write(chip, left_reg, val1);
 958                        else
 959                                snd_es1688_write(chip, left_reg, val1);
 960                }
 961                        
 962        }
 963        spin_unlock_irqrestore(&chip->reg_lock, flags);
 964        return change;
 965}
 966
 967static struct snd_kcontrol_new snd_es1688_controls[] = {
 968ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
 969ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
 970ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0),
 971ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0),
 972ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0),
 973ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0),
 974ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0),
 975ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
 976ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0),
 977ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
 978{
 979        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 980        .name = "Capture Source",
 981        .info = snd_es1688_info_mux,
 982        .get = snd_es1688_get_mux,
 983        .put = snd_es1688_put_mux,
 984},
 985};
 986
 987#define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2)
 988
 989static unsigned char snd_es1688_init_table[][2] = {
 990        { ES1688_MASTER_DEV, 0 },
 991        { ES1688_PCM_DEV, 0 },
 992        { ES1688_LINE_DEV, 0 },
 993        { ES1688_CD_DEV, 0 },
 994        { ES1688_FM_DEV, 0 },
 995        { ES1688_MIC_DEV, 0 },
 996        { ES1688_AUX_DEV, 0 },
 997        { ES1688_SPEAKER_DEV, 0 },
 998        { ES1688_RECLEV_DEV, 0 },
 999        { ES1688_REC_DEV, 0x17 }
1000};
1001                                        
1002int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip)
1003{
1004        unsigned int idx;
1005        int err;
1006        unsigned char reg, val;
1007
1008        if (snd_BUG_ON(!chip || !card))
1009                return -EINVAL;
1010
1011        strcpy(card->mixername, snd_es1688_chip_id(chip));
1012
1013        for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
1014                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0)
1015                        return err;
1016        }
1017        for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) {
1018                reg = snd_es1688_init_table[idx][0];
1019                val = snd_es1688_init_table[idx][1];
1020                if (reg < 0xa0)
1021                        snd_es1688_mixer_write(chip, reg, val);
1022                else
1023                        snd_es1688_write(chip, reg, val);
1024        }
1025        return 0;
1026}
1027
1028EXPORT_SYMBOL(snd_es1688_mixer_write);
1029EXPORT_SYMBOL(snd_es1688_create);
1030EXPORT_SYMBOL(snd_es1688_pcm);
1031EXPORT_SYMBOL(snd_es1688_mixer);
1032