linux-bk/sound/isa/ad1816a/ad1816a_lib.c
<<
>>
Prefs
   1
   2/*
   3    ad1816a.c - lowlevel code for Analog Devices AD1816A chip.
   4    Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
   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#include <sound/driver.h>
  22#include <linux/delay.h>
  23#include <linux/init.h>
  24#include <linux/interrupt.h>
  25#include <linux/slab.h>
  26#include <linux/ioport.h>
  27#include <sound/core.h>
  28#include <sound/ad1816a.h>
  29
  30#include <asm/io.h>
  31#include <asm/dma.h>
  32
  33MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
  34MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip");
  35MODULE_LICENSE("GPL");
  36
  37static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
  38{
  39        int timeout;
  40
  41        for (timeout = 1000; timeout-- > 0; udelay(10))
  42                if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY)
  43                        return 0;
  44
  45        snd_printk("chip busy.\n");
  46        return -EBUSY;
  47}
  48
  49static inline unsigned char snd_ad1816a_in(ad1816a_t *chip, unsigned char reg)
  50{
  51        snd_ad1816a_busy_wait(chip);
  52        return inb(AD1816A_REG(reg));
  53}
  54
  55static inline void snd_ad1816a_out(ad1816a_t *chip, unsigned char reg,
  56                            unsigned char value)
  57{
  58        snd_ad1816a_busy_wait(chip);
  59        outb(value, AD1816A_REG(reg));
  60}
  61
  62static inline void snd_ad1816a_out_mask(ad1816a_t *chip, unsigned char reg,
  63                                 unsigned char mask, unsigned char value)
  64{
  65        snd_ad1816a_out(chip, reg,
  66                (value & mask) | (snd_ad1816a_in(chip, reg) & ~mask));
  67}
  68
  69static unsigned short snd_ad1816a_read(ad1816a_t *chip, unsigned char reg)
  70{
  71        snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f);
  72        return snd_ad1816a_in(chip, AD1816A_INDIR_DATA_LOW) |
  73                (snd_ad1816a_in(chip, AD1816A_INDIR_DATA_HIGH) << 8);
  74}
  75
  76static void snd_ad1816a_write(ad1816a_t *chip, unsigned char reg,
  77                              unsigned short value)
  78{
  79        snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f);
  80        snd_ad1816a_out(chip, AD1816A_INDIR_DATA_LOW, value & 0xff);
  81        snd_ad1816a_out(chip, AD1816A_INDIR_DATA_HIGH, (value >> 8) & 0xff);
  82}
  83
  84static void snd_ad1816a_write_mask(ad1816a_t *chip, unsigned char reg,
  85                                   unsigned short mask, unsigned short value)
  86{
  87        snd_ad1816a_write(chip, reg,
  88                (value & mask) | (snd_ad1816a_read(chip, reg) & ~mask));
  89}
  90
  91
  92static unsigned char snd_ad1816a_get_format(ad1816a_t *chip,
  93                                            unsigned int format, int channels)
  94{
  95        unsigned char retval = AD1816A_FMT_LINEAR_8;
  96
  97        switch (format) {
  98        case SNDRV_PCM_FORMAT_MU_LAW:
  99                retval = AD1816A_FMT_ULAW_8;
 100                break;
 101        case SNDRV_PCM_FORMAT_A_LAW:
 102                retval = AD1816A_FMT_ALAW_8;
 103                break;
 104        case SNDRV_PCM_FORMAT_S16_LE:
 105                retval = AD1816A_FMT_LINEAR_16_LIT;
 106                break;
 107        case SNDRV_PCM_FORMAT_S16_BE:
 108                retval = AD1816A_FMT_LINEAR_16_BIG;
 109        }
 110        return (channels > 1) ? (retval | AD1816A_FMT_STEREO) : retval;
 111}
 112
 113static int snd_ad1816a_open(ad1816a_t *chip, unsigned int mode)
 114{
 115        unsigned long flags;
 116
 117        spin_lock_irqsave(&chip->lock, flags);
 118
 119        if (chip->mode & mode) {
 120                spin_unlock_irqrestore(&chip->lock, flags);
 121                return -EAGAIN;
 122        }
 123
 124        switch ((mode &= AD1816A_MODE_OPEN)) {
 125        case AD1816A_MODE_PLAYBACK:
 126                snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
 127                        AD1816A_PLAYBACK_IRQ_PENDING, 0x00);
 128                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 129                        AD1816A_PLAYBACK_IRQ_ENABLE, 0xffff);
 130                break;
 131        case AD1816A_MODE_CAPTURE:
 132                snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
 133                        AD1816A_CAPTURE_IRQ_PENDING, 0x00);
 134                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 135                        AD1816A_CAPTURE_IRQ_ENABLE, 0xffff);
 136                break;
 137        case AD1816A_MODE_TIMER:
 138                snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
 139                        AD1816A_TIMER_IRQ_PENDING, 0x00);
 140                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 141                        AD1816A_TIMER_IRQ_ENABLE, 0xffff);
 142        }
 143        chip->mode |= mode;
 144
 145        spin_unlock_irqrestore(&chip->lock, flags);
 146        return 0;
 147}
 148
 149static void snd_ad1816a_close(ad1816a_t *chip, unsigned int mode)
 150{
 151        unsigned long flags;
 152
 153        spin_lock_irqsave(&chip->lock, flags);
 154
 155        switch ((mode &= AD1816A_MODE_OPEN)) {
 156        case AD1816A_MODE_PLAYBACK:
 157                snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
 158                        AD1816A_PLAYBACK_IRQ_PENDING, 0x00);
 159                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 160                        AD1816A_PLAYBACK_IRQ_ENABLE, 0x0000);
 161                break;
 162        case AD1816A_MODE_CAPTURE:
 163                snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
 164                        AD1816A_CAPTURE_IRQ_PENDING, 0x00);
 165                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 166                        AD1816A_CAPTURE_IRQ_ENABLE, 0x0000);
 167                break;
 168        case AD1816A_MODE_TIMER:
 169                snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS,
 170                        AD1816A_TIMER_IRQ_PENDING, 0x00);
 171                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 172                        AD1816A_TIMER_IRQ_ENABLE, 0x0000);
 173        }
 174        if (!((chip->mode &= ~mode) & AD1816A_MODE_OPEN))
 175                chip->mode = 0;
 176
 177        spin_unlock_irqrestore(&chip->lock, flags);
 178}
 179
 180
 181static int snd_ad1816a_trigger(ad1816a_t *chip, unsigned char what,
 182                               int channel, int cmd)
 183{
 184        int error = 0;
 185
 186        switch (cmd) {
 187        case SNDRV_PCM_TRIGGER_START:
 188        case SNDRV_PCM_TRIGGER_STOP:
 189                spin_lock(&chip->lock);
 190                cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00;
 191                if (what & AD1816A_PLAYBACK_ENABLE)
 192                        snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
 193                                AD1816A_PLAYBACK_ENABLE, cmd);
 194                if (what & AD1816A_CAPTURE_ENABLE)
 195                        snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
 196                                AD1816A_CAPTURE_ENABLE, cmd);
 197                spin_unlock(&chip->lock);
 198                break;
 199        default:
 200                snd_printk("invalid trigger mode 0x%x.\n", what);
 201                error = -EINVAL;
 202        }
 203
 204        return error;
 205}
 206
 207static int snd_ad1816a_playback_trigger(snd_pcm_substream_t *substream, int cmd)
 208{
 209        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 210        return snd_ad1816a_trigger(chip, AD1816A_PLAYBACK_ENABLE,
 211                SNDRV_PCM_STREAM_PLAYBACK, cmd);
 212}
 213
 214static int snd_ad1816a_capture_trigger(snd_pcm_substream_t *substream, int cmd)
 215{
 216        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 217        return snd_ad1816a_trigger(chip, AD1816A_CAPTURE_ENABLE,
 218                SNDRV_PCM_STREAM_CAPTURE, cmd);
 219}
 220
 221static int snd_ad1816a_hw_params(snd_pcm_substream_t * substream,
 222                                 snd_pcm_hw_params_t * hw_params)
 223{
 224        return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 225}
 226
 227static int snd_ad1816a_hw_free(snd_pcm_substream_t * substream)
 228{
 229        return snd_pcm_lib_free_pages(substream);
 230}
 231
 232static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream)
 233{
 234        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 235        unsigned long flags;
 236        snd_pcm_runtime_t *runtime = substream->runtime;
 237        unsigned int size;
 238
 239        spin_lock_irqsave(&chip->lock, flags);
 240
 241        chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream);
 242        snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
 243                AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00);
 244
 245        snd_dma_program(chip->dma1, runtime->dma_addr, size,
 246                        DMA_MODE_WRITE | DMA_AUTOINIT);
 247
 248        snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, runtime->rate);
 249        snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
 250                AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
 251                snd_ad1816a_get_format(chip, runtime->format,
 252                        runtime->channels));
 253
 254        snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT,
 255                snd_pcm_lib_period_bytes(substream) / 4 - 1);
 256
 257        spin_unlock_irqrestore(&chip->lock, flags);
 258        return 0;
 259}
 260
 261static int snd_ad1816a_capture_prepare(snd_pcm_substream_t *substream)
 262{
 263        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 264        unsigned long flags;
 265        snd_pcm_runtime_t *runtime = substream->runtime;
 266        unsigned int size;
 267
 268        spin_lock_irqsave(&chip->lock, flags);
 269
 270        chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream);
 271        snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
 272                AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00);
 273
 274        snd_dma_program(chip->dma2, runtime->dma_addr, size,
 275                        DMA_MODE_READ | DMA_AUTOINIT);
 276
 277        snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, runtime->rate);
 278        snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
 279                AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
 280                snd_ad1816a_get_format(chip, runtime->format,
 281                        runtime->channels));
 282
 283        snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT,
 284                snd_pcm_lib_period_bytes(substream) / 4 - 1);
 285
 286        spin_unlock_irqrestore(&chip->lock, flags);
 287        return 0;
 288}
 289
 290
 291static snd_pcm_uframes_t snd_ad1816a_playback_pointer(snd_pcm_substream_t *substream)
 292{
 293        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 294        size_t ptr;
 295        if (!(chip->mode & AD1816A_MODE_PLAYBACK))
 296                return 0;
 297        ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
 298        return bytes_to_frames(substream->runtime, ptr);
 299}
 300
 301static snd_pcm_uframes_t snd_ad1816a_capture_pointer(snd_pcm_substream_t *substream)
 302{
 303        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 304        size_t ptr;
 305        if (!(chip->mode & AD1816A_MODE_CAPTURE))
 306                return 0;
 307        ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
 308        return bytes_to_frames(substream->runtime, ptr);
 309}
 310
 311
 312static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 313{
 314        ad1816a_t *chip = dev_id;
 315        unsigned char status;
 316
 317        spin_lock(&chip->lock);
 318        status = snd_ad1816a_in(chip, AD1816A_INTERRUPT_STATUS);
 319        spin_unlock(&chip->lock);
 320
 321        if ((status & AD1816A_PLAYBACK_IRQ_PENDING) && chip->playback_substream)
 322                snd_pcm_period_elapsed(chip->playback_substream);
 323
 324        if ((status & AD1816A_CAPTURE_IRQ_PENDING) && chip->capture_substream)
 325                snd_pcm_period_elapsed(chip->capture_substream);
 326
 327        if ((status & AD1816A_TIMER_IRQ_PENDING) && chip->timer)
 328                snd_timer_interrupt(chip->timer, chip->timer->sticks);
 329
 330        spin_lock(&chip->lock);
 331        snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00);
 332        spin_unlock(&chip->lock);
 333        return IRQ_HANDLED;
 334}
 335
 336
 337static snd_pcm_hardware_t snd_ad1816a_playback = {
 338        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 339                                 SNDRV_PCM_INFO_MMAP_VALID),
 340        .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
 341                                 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
 342                                 SNDRV_PCM_FMTBIT_S16_BE),
 343        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 344        .rate_min =             4000,
 345        .rate_max =             55200,
 346        .channels_min =         1,
 347        .channels_max =         2,
 348        .buffer_bytes_max =     (128*1024),
 349        .period_bytes_min =     64,
 350        .period_bytes_max =     (128*1024),
 351        .periods_min =          1,
 352        .periods_max =          1024,
 353        .fifo_size =            0,
 354};
 355
 356static snd_pcm_hardware_t snd_ad1816a_capture = {
 357        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 358                                 SNDRV_PCM_INFO_MMAP_VALID),
 359        .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
 360                                 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
 361                                 SNDRV_PCM_FMTBIT_S16_BE),
 362        .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 363        .rate_min =             4000,
 364        .rate_max =             55200,
 365        .channels_min =         1,
 366        .channels_max =         2,
 367        .buffer_bytes_max =     (128*1024),
 368        .period_bytes_min =     64,
 369        .period_bytes_max =     (128*1024),
 370        .periods_min =          1,
 371        .periods_max =          1024,
 372        .fifo_size =            0,
 373};
 374
 375#if 0 /* not used now */
 376static int snd_ad1816a_timer_close(snd_timer_t *timer)
 377{
 378        ad1816a_t *chip = snd_timer_chip(timer);
 379        snd_ad1816a_close(chip, AD1816A_MODE_TIMER);
 380        return 0;
 381}
 382
 383static int snd_ad1816a_timer_open(snd_timer_t *timer)
 384{
 385        ad1816a_t *chip = snd_timer_chip(timer);
 386        snd_ad1816a_open(chip, AD1816A_MODE_TIMER);
 387        return 0;
 388}
 389
 390static unsigned long snd_ad1816a_timer_resolution(snd_timer_t *timer)
 391{
 392        snd_assert(timer != NULL, return 0);
 393
 394        return 10000;
 395}
 396
 397static int snd_ad1816a_timer_start(snd_timer_t *timer)
 398{
 399        unsigned short bits;
 400        unsigned long flags;
 401        ad1816a_t *chip = snd_timer_chip(timer);
 402        spin_lock_irqsave(&chip->lock, flags);
 403        bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE);
 404
 405        if (!(bits & AD1816A_TIMER_ENABLE)) {
 406                snd_ad1816a_write(chip, AD1816A_TIMER_BASE_COUNT,
 407                        timer->sticks & 0xffff);
 408
 409                snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 410                        AD1816A_TIMER_ENABLE, 0xffff);
 411        }
 412        spin_unlock_irqrestore(&chip->lock, flags);
 413        return 0;
 414}
 415
 416static int snd_ad1816a_timer_stop(snd_timer_t *timer)
 417{
 418        unsigned long flags;
 419        ad1816a_t *chip = snd_timer_chip(timer);
 420        spin_lock_irqsave(&chip->lock, flags);
 421
 422        snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
 423                AD1816A_TIMER_ENABLE, 0x0000);
 424
 425        spin_unlock_irqrestore(&chip->lock, flags);
 426        return 0;
 427}
 428
 429static struct _snd_timer_hardware snd_ad1816a_timer_table = {
 430        .flags =        SNDRV_TIMER_HW_AUTO,
 431        .resolution =   10000,
 432        .ticks =        65535,
 433        .open =         snd_ad1816a_timer_open,
 434        .close =        snd_ad1816a_timer_close,
 435        .c_resolution = snd_ad1816a_timer_resolution,
 436        .start =        snd_ad1816a_timer_start,
 437        .stop =         snd_ad1816a_timer_stop,
 438};
 439#endif /* not used now */
 440
 441
 442static int snd_ad1816a_playback_open(snd_pcm_substream_t *substream)
 443{
 444        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 445        snd_pcm_runtime_t *runtime = substream->runtime;
 446        int error;
 447
 448        if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0)
 449                return error;
 450        snd_pcm_set_sync(substream);
 451        runtime->hw = snd_ad1816a_playback;
 452        snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
 453        snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
 454        chip->playback_substream = substream;
 455        return 0;
 456}
 457
 458static int snd_ad1816a_capture_open(snd_pcm_substream_t *substream)
 459{
 460        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 461        snd_pcm_runtime_t *runtime = substream->runtime;
 462        int error;
 463
 464        if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0)
 465                return error;
 466        snd_pcm_set_sync(substream);
 467        runtime->hw = snd_ad1816a_capture;
 468        snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
 469        snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
 470        chip->capture_substream = substream;
 471        return 0;
 472}
 473
 474static int snd_ad1816a_playback_close(snd_pcm_substream_t *substream)
 475{
 476        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 477
 478        chip->playback_substream = NULL;
 479        snd_ad1816a_close(chip, AD1816A_MODE_PLAYBACK);
 480        return 0;
 481}
 482
 483static int snd_ad1816a_capture_close(snd_pcm_substream_t *substream)
 484{
 485        ad1816a_t *chip = snd_pcm_substream_chip(substream);
 486
 487        chip->capture_substream = NULL;
 488        snd_ad1816a_close(chip, AD1816A_MODE_CAPTURE);
 489        return 0;
 490}
 491
 492
 493static void snd_ad1816a_init(ad1816a_t *chip)
 494{
 495        unsigned long flags;
 496
 497        spin_lock_irqsave(&chip->lock, flags);
 498
 499        snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00);
 500        snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
 501                AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00);
 502        snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
 503                AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00);
 504        snd_ad1816a_write(chip, AD1816A_INTERRUPT_ENABLE, 0x0000);
 505        snd_ad1816a_write_mask(chip, AD1816A_CHIP_CONFIG,
 506                AD1816A_CAPTURE_NOT_EQUAL | AD1816A_WSS_ENABLE, 0xffff);
 507        snd_ad1816a_write(chip, AD1816A_DSP_CONFIG, 0x0000);
 508        snd_ad1816a_write(chip, AD1816A_POWERDOWN_CTRL, 0x0000);
 509
 510        spin_unlock_irqrestore(&chip->lock, flags);
 511}
 512
 513static int snd_ad1816a_probe(ad1816a_t *chip)
 514{
 515        unsigned long flags;
 516
 517        spin_lock_irqsave(&chip->lock, flags);
 518
 519        switch (chip->version = snd_ad1816a_read(chip, AD1816A_VERSION_ID)) {
 520        case 0:
 521                chip->hardware = AD1816A_HW_AD1815;
 522                break;
 523        case 1:
 524                chip->hardware = AD1816A_HW_AD18MAX10;
 525                break;
 526        case 3:
 527                chip->hardware = AD1816A_HW_AD1816A;
 528                break;
 529        default:
 530                chip->hardware = AD1816A_HW_AUTO;
 531        }
 532
 533        spin_unlock_irqrestore(&chip->lock, flags);
 534        return 0;
 535}
 536
 537static int snd_ad1816a_free(ad1816a_t *chip)
 538{
 539        if (chip->res_port) {
 540                release_resource(chip->res_port);
 541                kfree_nocheck(chip->res_port);
 542        }
 543        if (chip->irq >= 0)
 544                free_irq(chip->irq, (void *) chip);
 545        if (chip->dma1 >= 0) {
 546                snd_dma_disable(chip->dma1);
 547                free_dma(chip->dma1);
 548        }
 549        if (chip->dma2 >= 0) {
 550                snd_dma_disable(chip->dma2);
 551                free_dma(chip->dma2);
 552        }
 553        kfree(chip);
 554        return 0;
 555}
 556
 557static int snd_ad1816a_dev_free(snd_device_t *device)
 558{
 559        ad1816a_t *chip = device->device_data;
 560        return snd_ad1816a_free(chip);
 561}
 562
 563static const char *snd_ad1816a_chip_id(ad1816a_t *chip)
 564{
 565        switch (chip->hardware) {
 566        case AD1816A_HW_AD1816A: return "AD1816A";
 567        case AD1816A_HW_AD1815: return "AD1815";
 568        case AD1816A_HW_AD18MAX10: return "AD18max10";
 569        default:
 570                snd_printk("Unknown chip version %d:%d.\n",
 571                        chip->version, chip->hardware);
 572                return "AD1816A - unknown";
 573        }
 574}
 575
 576int snd_ad1816a_create(snd_card_t *card,
 577                       unsigned long port, int irq, int dma1, int dma2,
 578                       ad1816a_t **rchip)
 579{
 580        static snd_device_ops_t ops = {
 581                .dev_free =     snd_ad1816a_dev_free,
 582        };
 583        int error;
 584        ad1816a_t *chip;
 585
 586        *rchip = NULL;
 587
 588        chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 589        if (chip == NULL)
 590                return -ENOMEM;
 591        chip->irq = -1;
 592        chip->dma1 = -1;
 593        chip->dma2 = -1;
 594
 595        if ((chip->res_port = request_region(port, 16, "AD1816A")) == NULL) {
 596                snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port);
 597                snd_ad1816a_free(chip);
 598                return -EBUSY;
 599        }
 600        if (request_irq(irq, snd_ad1816a_interrupt, SA_INTERRUPT, "AD1816A", (void *) chip)) {
 601                snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
 602                snd_ad1816a_free(chip);
 603                return -EBUSY;
 604        }
 605        chip->irq = irq;
 606        if (request_dma(dma1, "AD1816A - 1")) {
 607                snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1);
 608                snd_ad1816a_free(chip);
 609                return -EBUSY;
 610        }
 611        chip->dma1 = dma1;
 612        if (request_dma(dma2, "AD1816A - 2")) {
 613                snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2);
 614                snd_ad1816a_free(chip);
 615                return -EBUSY;
 616        }
 617        chip->dma2 = dma2;
 618
 619        chip->card = card;
 620        chip->port = port;
 621        spin_lock_init(&chip->lock);
 622
 623        if ((error = snd_ad1816a_probe(chip))) {
 624                snd_ad1816a_free(chip);
 625                return error;
 626        }
 627
 628        snd_ad1816a_init(chip);
 629
 630        /* Register device */
 631        if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 632                snd_ad1816a_free(chip);
 633                return error;
 634        }
 635
 636        *rchip = chip;
 637        return 0;
 638}
 639
 640static snd_pcm_ops_t snd_ad1816a_playback_ops = {
 641        .open =         snd_ad1816a_playback_open,
 642        .close =        snd_ad1816a_playback_close,
 643        .ioctl =        snd_pcm_lib_ioctl,
 644        .hw_params =    snd_ad1816a_hw_params,
 645        .hw_free =      snd_ad1816a_hw_free,
 646        .prepare =      snd_ad1816a_playback_prepare,
 647        .trigger =      snd_ad1816a_playback_trigger,
 648        .pointer =      snd_ad1816a_playback_pointer,
 649};
 650
 651static snd_pcm_ops_t snd_ad1816a_capture_ops = {
 652        .open =         snd_ad1816a_capture_open,
 653        .close =        snd_ad1816a_capture_close,
 654        .ioctl =        snd_pcm_lib_ioctl,
 655        .hw_params =    snd_ad1816a_hw_params,
 656        .hw_free =      snd_ad1816a_hw_free,
 657        .prepare =      snd_ad1816a_capture_prepare,
 658        .trigger =      snd_ad1816a_capture_trigger,
 659        .pointer =      snd_ad1816a_capture_pointer,
 660};
 661
 662static void snd_ad1816a_pcm_free(snd_pcm_t *pcm)
 663{
 664        ad1816a_t *chip = pcm->private_data;
 665        chip->pcm = NULL;
 666        snd_pcm_lib_preallocate_free_for_all(pcm);
 667}
 668
 669int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
 670{
 671        int error;
 672        snd_pcm_t *pcm;
 673
 674        if ((error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm)))
 675                return error;
 676
 677        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1816a_playback_ops);
 678        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1816a_capture_ops);
 679
 680        pcm->private_data = chip;
 681        pcm->private_free = snd_ad1816a_pcm_free;
 682        pcm->info_flags = (chip->dma1 == chip->dma2 ) ? SNDRV_PCM_INFO_JOINT_DUPLEX : 0;
 683
 684        strcpy(pcm->name, snd_ad1816a_chip_id(chip));
 685        snd_ad1816a_init(chip);
 686
 687        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 688                                              snd_dma_isa_data(),
 689                                              64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
 690
 691        chip->pcm = pcm;
 692        if (rpcm)
 693                *rpcm = pcm;
 694        return 0;
 695}
 696
 697#if 0 /* not used now */
 698static void snd_ad1816a_timer_free(snd_timer_t *timer)
 699{
 700        ad1816a_t *chip = timer->private_data;
 701        chip->timer = NULL;
 702}
 703
 704int snd_ad1816a_timer(ad1816a_t *chip, int device, snd_timer_t **rtimer)
 705{
 706        snd_timer_t *timer;
 707        snd_timer_id_t tid;
 708        int error;
 709
 710        tid.dev_class = SNDRV_TIMER_CLASS_CARD;
 711        tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
 712        tid.card = chip->card->number;
 713        tid.device = device;
 714        tid.subdevice = 0;
 715        if ((error = snd_timer_new(chip->card, "AD1816A", &tid, &timer)) < 0)
 716                return error;
 717        strcpy(timer->name, snd_ad1816a_chip_id(chip));
 718        timer->private_data = chip;
 719        timer->private_free = snd_ad1816a_timer_free;
 720        chip->timer = timer;
 721        timer->hw = snd_ad1816a_timer_table;
 722        if (rtimer)
 723                *rtimer = timer;
 724        return 0;
 725}
 726#endif /* not used now */
 727
 728/*
 729 *
 730 */
 731
 732static int snd_ad1816a_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 733{
 734        static char *texts[8] = {
 735                "Line", "Mix", "CD", "Synth", "Video",
 736                "Mic", "Phone",
 737        };
 738
 739        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 740        uinfo->count = 2;
 741        uinfo->value.enumerated.items = 7;
 742        if (uinfo->value.enumerated.item > 6)
 743                uinfo->value.enumerated.item = 6;
 744        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 745        return 0;
 746}
 747
 748static int snd_ad1816a_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 749{
 750        ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
 751        unsigned long flags;
 752        unsigned short val;
 753        
 754        spin_lock_irqsave(&chip->lock, flags);
 755        val = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL);
 756        spin_unlock_irqrestore(&chip->lock, flags);
 757        ucontrol->value.enumerated.item[0] = (val >> 12) & 7;
 758        ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
 759        return 0;
 760}
 761
 762static int snd_ad1816a_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 763{
 764        ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
 765        unsigned long flags;
 766        unsigned short val;
 767        int change;
 768        
 769        if (ucontrol->value.enumerated.item[0] > 6 ||
 770            ucontrol->value.enumerated.item[1] > 6)
 771                return -EINVAL;
 772        val = (ucontrol->value.enumerated.item[0] << 12) |
 773              (ucontrol->value.enumerated.item[1] << 4);
 774        spin_lock_irqsave(&chip->lock, flags);
 775        change = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL) != val;
 776        snd_ad1816a_write(chip, AD1816A_ADC_SOURCE_SEL, val);
 777        spin_unlock_irqrestore(&chip->lock, flags);
 778        return change;
 779}
 780
 781#define AD1816A_SINGLE(xname, reg, shift, mask, invert) \
 782{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \
 783  .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \
 784  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
 785
 786static int snd_ad1816a_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 787{
 788        int mask = (kcontrol->private_value >> 16) & 0xff;
 789
 790        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
 791        uinfo->count = 1;
 792        uinfo->value.integer.min = 0;
 793        uinfo->value.integer.max = mask;
 794        return 0;
 795}
 796
 797static int snd_ad1816a_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 798{
 799        ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
 800        unsigned long flags;
 801        int reg = kcontrol->private_value & 0xff;
 802        int shift = (kcontrol->private_value >> 8) & 0xff;
 803        int mask = (kcontrol->private_value >> 16) & 0xff;
 804        int invert = (kcontrol->private_value >> 24) & 0xff;
 805        
 806        spin_lock_irqsave(&chip->lock, flags);
 807        ucontrol->value.integer.value[0] = (snd_ad1816a_read(chip, reg) >> shift) & mask;
 808        spin_unlock_irqrestore(&chip->lock, flags);
 809        if (invert)
 810                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 811        return 0;
 812}
 813
 814static int snd_ad1816a_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 815{
 816        ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
 817        unsigned long flags;
 818        int reg = kcontrol->private_value & 0xff;
 819        int shift = (kcontrol->private_value >> 8) & 0xff;
 820        int mask = (kcontrol->private_value >> 16) & 0xff;
 821        int invert = (kcontrol->private_value >> 24) & 0xff;
 822        int change;
 823        unsigned short old_val, val;
 824        
 825        val = (ucontrol->value.integer.value[0] & mask);
 826        if (invert)
 827                val = mask - val;
 828        val <<= shift;
 829        spin_lock_irqsave(&chip->lock, flags);
 830        old_val = snd_ad1816a_read(chip, reg);
 831        val = (old_val & ~(mask << shift)) | val;
 832        change = val != old_val;
 833        snd_ad1816a_write(chip, reg, val);
 834        spin_unlock_irqrestore(&chip->lock, flags);
 835        return change;
 836}
 837
 838#define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
 839{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \
 840  .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \
 841  .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) }
 842
 843static int snd_ad1816a_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 844{
 845        int mask = (kcontrol->private_value >> 16) & 0xff;
 846
 847        uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
 848        uinfo->count = 2;
 849        uinfo->value.integer.min = 0;
 850        uinfo->value.integer.max = mask;
 851        return 0;
 852}
 853
 854static int snd_ad1816a_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 855{
 856        ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
 857        unsigned long flags;
 858        int reg = kcontrol->private_value & 0xff;
 859        int shift_left = (kcontrol->private_value >> 8) & 0x0f;
 860        int shift_right = (kcontrol->private_value >> 12) & 0x0f;
 861        int mask = (kcontrol->private_value >> 16) & 0xff;
 862        int invert = (kcontrol->private_value >> 24) & 0xff;
 863        unsigned short val;
 864        
 865        spin_lock_irqsave(&chip->lock, flags);
 866        val = snd_ad1816a_read(chip, reg);
 867        ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
 868        ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
 869        spin_unlock_irqrestore(&chip->lock, flags);
 870        if (invert) {
 871                ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 872                ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
 873        }
 874        return 0;
 875}
 876
 877static int snd_ad1816a_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 878{
 879        ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
 880        unsigned long flags;
 881        int reg = kcontrol->private_value & 0xff;
 882        int shift_left = (kcontrol->private_value >> 8) & 0x0f;
 883        int shift_right = (kcontrol->private_value >> 12) & 0x0f;
 884        int mask = (kcontrol->private_value >> 16) & 0xff;
 885        int invert = (kcontrol->private_value >> 24) & 0xff;
 886        int change;
 887        unsigned short old_val, val1, val2;
 888        
 889        val1 = ucontrol->value.integer.value[0] & mask;
 890        val2 = ucontrol->value.integer.value[1] & mask;
 891        if (invert) {
 892                val1 = mask - val1;
 893                val2 = mask - val2;
 894        }
 895        val1 <<= shift_left;
 896        val2 <<= shift_right;
 897        spin_lock_irqsave(&chip->lock, flags);
 898        old_val = snd_ad1816a_read(chip, reg);
 899        val1 = (old_val & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
 900        change = val1 != old_val;
 901        snd_ad1816a_write(chip, reg, val1);
 902        spin_unlock_irqrestore(&chip->lock, flags);
 903        return change;
 904}
 905
 906static snd_kcontrol_new_t snd_ad1816a_controls[] = {
 907AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
 908AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1),
 909AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1),
 910AD1816A_DOUBLE("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1),
 911AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1),
 912AD1816A_DOUBLE("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1),
 913AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1),
 914AD1816A_DOUBLE("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1),
 915AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1),
 916AD1816A_DOUBLE("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1),
 917AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1),
 918AD1816A_DOUBLE("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1),
 919AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1),
 920AD1816A_SINGLE("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1),
 921AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0),
 922AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1),
 923AD1816A_DOUBLE("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1),
 924AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1),
 925AD1816A_SINGLE("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1),
 926AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1),
 927AD1816A_SINGLE("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1),
 928{
 929        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 930        .name = "Capture Source",
 931        .info = snd_ad1816a_info_mux,
 932        .get = snd_ad1816a_get_mux,
 933        .put = snd_ad1816a_put_mux,
 934},
 935AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1),
 936AD1816A_DOUBLE("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0),
 937AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1),
 938AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0),
 939};
 940                                        
 941int snd_ad1816a_mixer(ad1816a_t *chip)
 942{
 943        snd_card_t *card;
 944        unsigned int idx;
 945        int err;
 946
 947        snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
 948
 949        card = chip->card;
 950
 951        strcpy(card->mixername, snd_ad1816a_chip_id(chip));
 952
 953        for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) {
 954                if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0)
 955                        return err;
 956        }
 957        return 0;
 958}
 959
 960EXPORT_SYMBOL(snd_ad1816a_create);
 961EXPORT_SYMBOL(snd_ad1816a_pcm);
 962EXPORT_SYMBOL(snd_ad1816a_mixer);
 963
 964static int __init alsa_ad1816a_init(void)
 965{
 966        return 0;
 967}
 968
 969static void __exit alsa_ad1816a_exit(void)
 970{
 971}
 972
 973module_init(alsa_ad1816a_init)
 974module_exit(alsa_ad1816a_exit)
 975
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.