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 <sound/core.h>
  29#include <sound/es1688.h>
  30#include <sound/initval.h>
  31
  32#include <asm/io.h>
  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 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 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 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 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        if (chip->res_port)
 618                release_and_free_resource(chip->res_port);
 619        if (chip->irq >= 0)
 620                free_irq(chip->irq, (void *) chip);
 621        if (chip->dma8 >= 0) {
 622                disable_dma(chip->dma8);
 623                free_dma(chip->dma8);
 624        }
 625        return 0;
 626}
 627
 628static int snd_es1688_dev_free(struct snd_device *device)
 629{
 630        struct snd_es1688 *chip = device->device_data;
 631        return snd_es1688_free(chip);
 632}
 633
 634static const char *snd_es1688_chip_id(struct snd_es1688 *chip)
 635{
 636        static char tmp[16];
 637        sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f);
 638        return tmp;
 639}
 640
 641int snd_es1688_create(struct snd_card *card,
 642                      struct snd_es1688 *chip,
 643                      unsigned long port,
 644                      unsigned long mpu_port,
 645                      int irq,
 646                      int mpu_irq,
 647                      int dma8,
 648                      unsigned short hardware)
 649{
 650        static struct snd_device_ops ops = {
 651                .dev_free =     snd_es1688_dev_free,
 652        };
 653                                
 654        int err;
 655
 656        if (chip == NULL)
 657                return -ENOMEM;
 658        chip->irq = -1;
 659        chip->dma8 = -1;
 660        chip->hardware = ES1688_HW_UNDEF;
 661        
 662        chip->res_port = request_region(port + 4, 12, "ES1688");
 663        if (chip->res_port == NULL) {
 664                snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4);
 665                err = -EBUSY;
 666                goto exit;
 667        }
 668
 669        err = request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip);
 670        if (err < 0) {
 671                snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq);
 672                goto exit;
 673        }
 674
 675        chip->irq = irq;
 676        err = request_dma(dma8, "ES1688");
 677
 678        if (err < 0) {
 679                snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8);
 680                goto exit;
 681        }
 682        chip->dma8 = dma8;
 683
 684        spin_lock_init(&chip->reg_lock);
 685        spin_lock_init(&chip->mixer_lock);
 686        chip->port = port;
 687        mpu_port &= ~0x000f;
 688        if (mpu_port < 0x300 || mpu_port > 0x330)
 689                mpu_port = 0;
 690        chip->mpu_port = mpu_port;
 691        chip->mpu_irq = mpu_irq;
 692        chip->hardware = hardware;
 693
 694        err = snd_es1688_probe(chip);
 695        if (err < 0)
 696                goto exit;
 697
 698        err = snd_es1688_init(chip, 1);
 699        if (err < 0)
 700                goto exit;
 701
 702        /* Register device */
 703        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
 704exit:
 705        if (err)
 706                snd_es1688_free(chip);
 707        return err;
 708}
 709
 710static struct snd_pcm_ops snd_es1688_playback_ops = {
 711        .open =                 snd_es1688_playback_open,
 712        .close =                snd_es1688_playback_close,
 713        .ioctl =                snd_es1688_ioctl,
 714        .hw_params =            snd_es1688_hw_params,
 715        .hw_free =              snd_es1688_hw_free,
 716        .prepare =              snd_es1688_playback_prepare,
 717        .trigger =              snd_es1688_playback_trigger,
 718        .pointer =              snd_es1688_playback_pointer,
 719};
 720
 721static struct snd_pcm_ops snd_es1688_capture_ops = {
 722        .open =                 snd_es1688_capture_open,
 723        .close =                snd_es1688_capture_close,
 724        .ioctl =                snd_es1688_ioctl,
 725        .hw_params =            snd_es1688_hw_params,
 726        .hw_free =              snd_es1688_hw_free,
 727        .prepare =              snd_es1688_capture_prepare,
 728        .trigger =              snd_es1688_capture_trigger,
 729        .pointer =              snd_es1688_capture_pointer,
 730};
 731
 732int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip,
 733                   int device, struct snd_pcm **rpcm)
 734{
 735        struct snd_pcm *pcm;
 736        int err;
 737
 738        err = snd_pcm_new(card, "ESx688", device, 1, 1, &pcm);
 739        if (err < 0)
 740                return err;
 741
 742        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1688_playback_ops);
 743        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops);
 744
 745        pcm->private_data = chip;
 746        pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
 747        sprintf(pcm->name, snd_es1688_chip_id(chip));
 748        chip->pcm = pcm;
 749
 750        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 751                                              snd_dma_isa_data(),
 752                                              64*1024, 64*1024);
 753
 754        if (rpcm)
 755                *rpcm = pcm;
 756        return 0;
 757}
 758
 759/*
 760 *  MIXER part
 761 */
 762
 763static int snd_es1688_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 764{
 765        static char *texts[9] = {
 766                "Mic", "Mic Master", "CD", "AOUT",
 767                "Mic1", "Mix", "Line", "Master"
 768        };
 769
 770        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 771        uinfo->count = 1;
 772        uinfo->value.enumerated.items = 8;
 773        if (uinfo->value.enumerated.item > 7)
 774                uinfo->value.enumerated.item = 7;
 775        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 776        return 0;
 777}
 778
 779static int snd_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 780{
 781        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 782        ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7;
 783        return 0;
 784}
 785
 786static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 787{
 788        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 789        unsigned long flags;
 790        unsigned char oval, nval;
 791        int change;
 792        
 793        if (ucontrol->value.enumerated.item[0] > 8)
 794                return -EINVAL;
 795        spin_lock_irqsave(&chip->reg_lock, flags);
 796        oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV);
 797        nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15);
 798        change = nval != oval;
 799        if (change)
 800                snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval);
 801        spin_unlock_irqrestore(&chip->reg_lock, flags);
 802        return change;
 803}
 804
 805#define ES1688_SINGLE(xname, xindex, reg, shift, mask, invert) \
 806{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
 807  .info = snd_es1688_info_single, \
 808  .get = snd_es1688_get_single, .put = snd_es1688_put_single, \
 809  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
 810
 811static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 812{
 813        int mask = (kcontrol->private_value >> 16) & 0xff;
 814
 815        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
 816        uinfo->count = 1;
 817        uinfo->value.integer.min = 0;
 818        uinfo->value.integer.max = mask;
 819        return 0;
 820}
 821
 822static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 823{
 824        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 825        unsigned long flags;
 826        int reg = kcontrol->private_value & 0xff;
 827        int shift = (kcontrol->private_value >> 8) & 0xff;
 828        int mask = (kcontrol->private_value >> 16) & 0xff;
 829        int invert = (kcontrol->private_value >> 24) & 0xff;
 830        
 831        spin_lock_irqsave(&chip->reg_lock, flags);
 832        ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask;
 833        spin_unlock_irqrestore(&chip->reg_lock, flags);
 834        if (invert)
 835                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 836        return 0;
 837}
 838
 839static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 840{
 841        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 842        unsigned long flags;
 843        int reg = kcontrol->private_value & 0xff;
 844        int shift = (kcontrol->private_value >> 8) & 0xff;
 845        int mask = (kcontrol->private_value >> 16) & 0xff;
 846        int invert = (kcontrol->private_value >> 24) & 0xff;
 847        int change;
 848        unsigned char oval, nval;
 849        
 850        nval = (ucontrol->value.integer.value[0] & mask);
 851        if (invert)
 852                nval = mask - nval;
 853        nval <<= shift;
 854        spin_lock_irqsave(&chip->reg_lock, flags);
 855        oval = snd_es1688_mixer_read(chip, reg);
 856        nval = (oval & ~(mask << shift)) | nval;
 857        change = nval != oval;
 858        if (change)
 859                snd_es1688_mixer_write(chip, reg, nval);
 860        spin_unlock_irqrestore(&chip->reg_lock, flags);
 861        return change;
 862}
 863
 864#define ES1688_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
 865{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
 866  .info = snd_es1688_info_double, \
 867  .get = snd_es1688_get_double, .put = snd_es1688_put_double, \
 868  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
 869
 870static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 871{
 872        int mask = (kcontrol->private_value >> 24) & 0xff;
 873
 874        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
 875        uinfo->count = 2;
 876        uinfo->value.integer.min = 0;
 877        uinfo->value.integer.max = mask;
 878        return 0;
 879}
 880
 881static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 882{
 883        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 884        unsigned long flags;
 885        int left_reg = kcontrol->private_value & 0xff;
 886        int right_reg = (kcontrol->private_value >> 8) & 0xff;
 887        int shift_left = (kcontrol->private_value >> 16) & 0x07;
 888        int shift_right = (kcontrol->private_value >> 19) & 0x07;
 889        int mask = (kcontrol->private_value >> 24) & 0xff;
 890        int invert = (kcontrol->private_value >> 22) & 1;
 891        unsigned char left, right;
 892        
 893        spin_lock_irqsave(&chip->reg_lock, flags);
 894        if (left_reg < 0xa0)
 895                left = snd_es1688_mixer_read(chip, left_reg);
 896        else
 897                left = snd_es1688_read(chip, left_reg);
 898        if (left_reg != right_reg) {
 899                if (right_reg < 0xa0) 
 900                        right = snd_es1688_mixer_read(chip, right_reg);
 901                else
 902                        right = snd_es1688_read(chip, right_reg);
 903        } else
 904                right = left;
 905        spin_unlock_irqrestore(&chip->reg_lock, flags);
 906        ucontrol->value.integer.value[0] = (left >> shift_left) & mask;
 907        ucontrol->value.integer.value[1] = (right >> shift_right) & mask;
 908        if (invert) {
 909                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 910                ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
 911        }
 912        return 0;
 913}
 914
 915static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 916{
 917        struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
 918        unsigned long flags;
 919        int left_reg = kcontrol->private_value & 0xff;
 920        int right_reg = (kcontrol->private_value >> 8) & 0xff;
 921        int shift_left = (kcontrol->private_value >> 16) & 0x07;
 922        int shift_right = (kcontrol->private_value >> 19) & 0x07;
 923        int mask = (kcontrol->private_value >> 24) & 0xff;
 924        int invert = (kcontrol->private_value >> 22) & 1;
 925        int change;
 926        unsigned char val1, val2, oval1, oval2;
 927        
 928        val1 = ucontrol->value.integer.value[0] & mask;
 929        val2 = ucontrol->value.integer.value[1] & mask;
 930        if (invert) {
 931                val1 = mask - val1;
 932                val2 = mask - val2;
 933        }
 934        val1 <<= shift_left;
 935        val2 <<= shift_right;
 936        spin_lock_irqsave(&chip->reg_lock, flags);
 937        if (left_reg != right_reg) {
 938                if (left_reg < 0xa0)
 939                        oval1 = snd_es1688_mixer_read(chip, left_reg);
 940                else
 941                        oval1 = snd_es1688_read(chip, left_reg);
 942                if (right_reg < 0xa0)
 943                        oval2 = snd_es1688_mixer_read(chip, right_reg);
 944                else
 945                        oval2 = snd_es1688_read(chip, right_reg);
 946                val1 = (oval1 & ~(mask << shift_left)) | val1;
 947                val2 = (oval2 & ~(mask << shift_right)) | val2;
 948                change = val1 != oval1 || val2 != oval2;
 949                if (change) {
 950                        if (left_reg < 0xa0)
 951                                snd_es1688_mixer_write(chip, left_reg, val1);
 952                        else
 953                                snd_es1688_write(chip, left_reg, val1);
 954                        if (right_reg < 0xa0)
 955                                snd_es1688_mixer_write(chip, right_reg, val1);
 956                        else
 957                                snd_es1688_write(chip, right_reg, val1);
 958                }
 959        } else {
 960                if (left_reg < 0xa0)
 961                        oval1 = snd_es1688_mixer_read(chip, left_reg);
 962                else
 963                        oval1 = snd_es1688_read(chip, left_reg);
 964                val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
 965                change = val1 != oval1;
 966                if (change) {
 967                        if (left_reg < 0xa0)
 968                                snd_es1688_mixer_write(chip, left_reg, val1);
 969                        else
 970                                snd_es1688_write(chip, left_reg, val1);
 971                }
 972                        
 973        }
 974        spin_unlock_irqrestore(&chip->reg_lock, flags);
 975        return change;
 976}
 977
 978static struct snd_kcontrol_new snd_es1688_controls[] = {
 979ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
 980ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
 981ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0),
 982ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0),
 983ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0),
 984ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0),
 985ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0),
 986ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
 987ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0),
 988ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
 989{
 990        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 991        .name = "Capture Source",
 992        .info = snd_es1688_info_mux,
 993        .get = snd_es1688_get_mux,
 994        .put = snd_es1688_put_mux,
 995},
 996};
 997
 998#define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2)
 999
1000static unsigned char snd_es1688_init_table[][2] = {
1001        { ES1688_MASTER_DEV, 0 },
1002        { ES1688_PCM_DEV, 0 },
1003        { ES1688_LINE_DEV, 0 },
1004        { ES1688_CD_DEV, 0 },
1005        { ES1688_FM_DEV, 0 },
1006        { ES1688_MIC_DEV, 0 },
1007        { ES1688_AUX_DEV, 0 },
1008        { ES1688_SPEAKER_DEV, 0 },
1009        { ES1688_RECLEV_DEV, 0 },
1010        { ES1688_REC_DEV, 0x17 }
1011};
1012                                        
1013int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip)
1014{
1015        unsigned int idx;
1016        int err;
1017        unsigned char reg, val;
1018
1019        if (snd_BUG_ON(!chip || !card))
1020                return -EINVAL;
1021
1022        strcpy(card->mixername, snd_es1688_chip_id(chip));
1023
1024        for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
1025                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0)
1026                        return err;
1027        }
1028        for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) {
1029                reg = snd_es1688_init_table[idx][0];
1030                val = snd_es1688_init_table[idx][1];
1031                if (reg < 0xa0)
1032                        snd_es1688_mixer_write(chip, reg, val);
1033                else
1034                        snd_es1688_write(chip, reg, val);
1035        }
1036        return 0;
1037}
1038
1039EXPORT_SYMBOL(snd_es1688_mixer_write);
1040EXPORT_SYMBOL(snd_es1688_create);
1041EXPORT_SYMBOL(snd_es1688_pcm);
1042EXPORT_SYMBOL(snd_es1688_mixer);
1043
1044/*
1045 *  INIT part
1046 */
1047
1048static int __init alsa_es1688_init(void)
1049{
1050        return 0;
1051}
1052
1053static void __exit alsa_es1688_exit(void)
1054{
1055}
1056
1057module_init(alsa_es1688_init)
1058module_exit(alsa_es1688_exit)
1059